@@ -3,12 +3,14 @@ package image
33import (
44 "crypto/sha256"
55 "encoding/base64"
6+ "encoding/json"
67 "fmt"
78 "regexp"
89 "strings"
910 "sync"
1011 "time"
1112
13+ imageapi "github.com/openshift/api/image/v1"
1214 "k8s.io/apimachinery/pkg/util/sets"
1315 k8simage "k8s.io/kubernetes/test/utils/image"
1416)
1921 fromRepository string
2022 images map [string ]string
2123
24+ releasePullSpecInitializationLock sync.RWMutex
25+ releasePullSpecInitialized bool
26+ availablePullSpecs = map [string ]string {
27+ "cli" : "image-registry.openshift-image-registry.svc:5000/openshift/cli:latest" ,
28+ "tools" : "image-registry.openshift-image-registry.svc:5000/openshift/tools:latest" ,
29+ }
30+ imageRegistryPullSpecRegex = regexp .MustCompile (`image-registry\.openshift-image-registry\.svc:5000\/openshift\/([A-Za-z0-9._-]+)[@:A-Za-z0-9._-]*` )
31+
2232 allowedImages = map [string ]k8simage.ImageID {
2333 // used by jenkins tests
2434 "quay.io/redhat-developer/nfs-server:1.1" : - 1 ,
@@ -106,6 +116,27 @@ func ReplaceContents(data []byte) ([]byte, error) {
106116 patterns [to ] = re
107117 }
108118
119+ // find any references to image-registry.openshift-image-registry.svc:5000/openshift/<image>:<tag>
120+ // append pattern match for appropriate PullSpec if one exists
121+ allMatches := imageRegistryPullSpecRegex .FindAllStringSubmatch (string (data ), - 1 )
122+ for _ , match := range allMatches {
123+ if len (match ) != 2 {
124+ continue
125+ }
126+ exactMatchedPullSpec := match [0 ]
127+ tagMatchedPullSpec := match [1 ]
128+ to , found := GetPullSpecFor (tagMatchedPullSpec )
129+ if ! found || to == exactMatchedPullSpec {
130+ continue
131+ }
132+ pattern := fmt .Sprintf (exactImageFormat , regexp .QuoteMeta (exactMatchedPullSpec ))
133+ re , err := regexp .Compile (pattern )
134+ if err != nil {
135+ return nil , err
136+ }
137+ patterns [to ] = re
138+ }
139+
109140 for to , pattern := range patterns {
110141 data = pattern .ReplaceAll (data , []byte (to ))
111142 }
@@ -146,15 +177,15 @@ the test/extended/util/image/README.md file.`, image))
146177// to avoid the need to add packages by using simpler concepts or consider
147178// extending an existing image.
148179func ShellImage () string {
149- return "image-registry.openshift-image-registry.svc:5000/openshift/ tools:latest"
180+ return GetPullSpecForOrPanic ( " tools" )
150181}
151182
152183// LimitedShellImage returns a docker pull spec that any pod on the cluster
153184// has access to that contains bash and standard commandline tools.
154185// This image should be used when you only need oc and can't use the shell image.
155186// This image has oc.
156187func LimitedShellImage () string {
157- return "image-registry.openshift-image-registry.svc:5000/openshift/ cli:latest"
188+ return GetPullSpecForOrPanic ( " cli" )
158189}
159190
160191// OpenLDAPTestImage returns the LDAP test image.
@@ -236,3 +267,54 @@ func GetMappedImages(originalImages map[string]k8simage.ImageID, repo string) ma
236267 }
237268 return configs
238269}
270+
271+ func GetPullSpecFor (image string ) (string , bool ) {
272+ if spec , found := availablePullSpecs [image ]; found {
273+ return spec , true
274+ }
275+ return "" , false
276+ }
277+
278+ func GetPullSpecForOrPanic (image string ) string {
279+ spec , found := GetPullSpecFor (image )
280+ if ! found {
281+ panic (fmt .Sprintf ("could not find PullSpec for (%s)" , image ))
282+ }
283+ return spec
284+ }
285+
286+ // InitializeReleasePullSpecString initializes a mapping with the PullSpec ImageStream string from
287+ // the release payload
288+ //
289+ // When running in clusters that do not have ImageRegistry installed it is necessary to use the full
290+ // PullSpec for ImageRegistry containers such as `cli` or `tools`, Pass in an imageStreamString of
291+ // the discovered PullSpec (ex. oc adm release info `-ojsonpath='{.references}'). This method will then
292+ // initialize the package with the PullSpec for that release.
293+ //
294+ // Using GetPullSpecFor(), ShellImage() and LimitedShellImage() will return the appropriate
295+ // PullSpec, either the ReleasePayload or ImageRegistry.
296+ func InitializeReleasePullSpecString (imageStreamString string , hasNoImageRegistry bool ) error {
297+ releasePullSpecInitializationLock .Lock ()
298+ defer releasePullSpecInitializationLock .Unlock ()
299+ if releasePullSpecInitialized {
300+ panic ("attempt to double initialize ReleasePullSpec" )
301+ }
302+ images := & imageapi.ImageStream {}
303+ err := json .Unmarshal ([]byte (imageStreamString ), images )
304+ if err != nil {
305+ return fmt .Errorf ("failed to unmarshal release ImageStream string: %w" , err )
306+ }
307+
308+ for _ , tag := range images .Spec .Tags {
309+ if tag .From .Kind != "DockerImage" {
310+ continue
311+ }
312+ // If an available pullthrough spec is already defined, and we do have an ImageRegistry
313+ // we leave it alone
314+ if _ , available := availablePullSpecs [tag .Name ]; available && ! hasNoImageRegistry {
315+ continue
316+ }
317+ availablePullSpecs [tag .Name ] = tag .From .Name
318+ }
319+ return nil
320+ }
0 commit comments