77 "path/filepath"
88 "strings"
99
10+ imageclientset "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1"
1011 coreapi "k8s.io/api/core/v1"
1112 rbacapi "k8s.io/api/rbac/v1"
1213 "k8s.io/apimachinery/pkg/api/errors"
@@ -53,6 +54,7 @@ type multiStageTestStep struct {
5354 secretClient coreclientset.SecretsGetter
5455 saClient coreclientset.ServiceAccountsGetter
5556 rbacClient rbacclientset.RbacV1Interface
57+ isClient imageclientset.ImageStreamsGetter
5658 artifactDir string
5759 jobSpec * api.JobSpec
5860 pre , test , post []api.LiteralTestStep
@@ -68,10 +70,11 @@ func MultiStageTestStep(
6870 secretClient coreclientset.SecretsGetter ,
6971 saClient coreclientset.ServiceAccountsGetter ,
7072 rbacClient rbacclientset.RbacV1Interface ,
73+ isClient imageclientset.ImageStreamsGetter ,
7174 artifactDir string ,
7275 jobSpec * api.JobSpec ,
7376) api.Step {
74- return newMultiStageTestStep (testConfig , config , params , podClient , secretClient , saClient , rbacClient , artifactDir , jobSpec )
77+ return newMultiStageTestStep (testConfig , config , params , podClient , secretClient , saClient , rbacClient , isClient , artifactDir , jobSpec )
7578}
7679
7780func newMultiStageTestStep (
@@ -82,6 +85,7 @@ func newMultiStageTestStep(
8285 secretClient coreclientset.SecretsGetter ,
8386 saClient coreclientset.ServiceAccountsGetter ,
8487 rbacClient rbacclientset.RbacV1Interface ,
88+ isClient imageclientset.ImageStreamsGetter ,
8589 artifactDir string ,
8690 jobSpec * api.JobSpec ,
8791) * multiStageTestStep {
@@ -99,6 +103,7 @@ func newMultiStageTestStep(
99103 secretClient : secretClient ,
100104 saClient : saClient ,
101105 rbacClient : rbacClient ,
106+ isClient : isClient ,
102107 artifactDir : artifactDir ,
103108 jobSpec : jobSpec ,
104109 pre : ms .Pre ,
@@ -179,6 +184,13 @@ func (s *multiStageTestStep) Requires() (ret []api.StepLink) {
179184 if link , ok := step .FromImageTag (); ok {
180185 internalLinks [link ] = struct {}{}
181186 }
187+
188+ for _ , dependency := range step .Dependencies {
189+ imageStream , name := s .parts (dependency )
190+ if link , ok := utils .LinkForImage (imageStream , name ); ok {
191+ ret = append (ret , link )
192+ }
193+ }
182194 }
183195 for link := range internalLinks {
184196 ret = append (ret , api .InternalImageLink (link ))
@@ -197,6 +209,17 @@ func (s *multiStageTestStep) Requires() (ret []api.StepLink) {
197209 return
198210}
199211
212+ // parts returns the imageStream and tag name from a user-provided
213+ // reference to an image in the test namespace
214+ func (s multiStageTestStep ) parts (dependency api.StepDependency ) (string , string ) {
215+ if ! strings .Contains (dependency .Name , ":" ) {
216+ return s .imageStreamFor (dependency .Name ), dependency .Name
217+ } else {
218+ parts := strings .Split (dependency .Name , ":" )
219+ return parts [0 ], parts [1 ]
220+ }
221+ }
222+
200223func (s * multiStageTestStep ) Creates () []api.StepLink { return nil }
201224func (s * multiStageTestStep ) Provides () api.ParameterMap {
202225 return nil
@@ -321,6 +344,21 @@ func (s *multiStageTestStep) runSteps(
321344 return utilerrors .NewAggregate (errs )
322345}
323346
347+ // imageStreamFor guesses at the ImageStream that will hold a tag.
348+ // We use this to decipher the user's intent when they provide a
349+ // naked tag in configuration; we support such behavior in order to
350+ // allow users a simpler workflow for the most common cases, like
351+ // referring to `pipeline:src`. If they refer to an ambiguous image,
352+ // however, they will get bad behavior and will need to specify an
353+ // ImageStrem as well, for instance release-initial:installer.
354+ func (s * multiStageTestStep ) imageStreamFor (image string ) string {
355+ if s .config .IsPipelineImage (image ) || s .config .BuildsImage (image ) {
356+ return api .PipelineImageStream
357+ } else {
358+ return api .StableImageStream
359+ }
360+ }
361+
324362func (s * multiStageTestStep ) generatePods (steps []api.LiteralTestStep , env []coreapi.EnvVar ,
325363 hasPrevErrs bool ) ([]coreapi.Pod , error ) {
326364 var ret []coreapi.Pod
@@ -335,11 +373,7 @@ func (s *multiStageTestStep) generatePods(steps []api.LiteralTestStep, env []cor
335373 if link , ok := step .FromImageTag (); ok {
336374 image = fmt .Sprintf ("%s:%s" , api .PipelineImageStream , link )
337375 } else {
338- if s .config .IsPipelineImage (image ) || s .config .BuildsImage (image ) {
339- image = fmt .Sprintf ("%s:%s" , api .PipelineImageStream , image )
340- } else {
341- image = fmt .Sprintf ("%s:%s" , api .StableImageStream , image )
342- }
376+ image = fmt .Sprintf ("%s:%s" , s .imageStreamFor (image ), image )
343377 }
344378 resources , err := resourcesFor (step .Resources )
345379 if err != nil {
@@ -365,6 +399,12 @@ func (s *multiStageTestStep) generatePods(steps []api.LiteralTestStep, env []cor
365399 }... )
366400 container .Env = append (container .Env , env ... )
367401 container .Env = append (container .Env , s .generateParams (step .Environment )... )
402+ depEnv , depErrs := s .envForDependencies (step )
403+ if len (depErrs ) != 0 {
404+ errs = append (errs , depErrs ... )
405+ continue
406+ }
407+ container .Env = append (container .Env , depEnv ... )
368408 if owner := s .jobSpec .Owner (); owner != nil {
369409 pod .OwnerReferences = append (pod .OwnerReferences , * owner )
370410 }
@@ -381,6 +421,23 @@ func (s *multiStageTestStep) generatePods(steps []api.LiteralTestStep, env []cor
381421 return ret , utilerrors .NewAggregate (errs )
382422}
383423
424+ func (s * multiStageTestStep ) envForDependencies (step api.LiteralTestStep ) ([]coreapi.EnvVar , []error ) {
425+ var env []coreapi.EnvVar
426+ var errs []error
427+ for _ , dependency := range step .Dependencies {
428+ imageStream , name := s .parts (dependency )
429+ ref , err := utils .ImageDigestFor (s .isClient , s .jobSpec .Namespace , imageStream , name )()
430+ if err != nil {
431+ errs = append (errs , fmt .Errorf ("could not determine image pull spec for image %s on step %s" , dependency .Name , step .As ))
432+ continue
433+ }
434+ env = append (env , coreapi.EnvVar {
435+ Name : dependency .Env , Value : ref ,
436+ })
437+ }
438+ return env , errs
439+ }
440+
384441func addSecretWrapper (pod * coreapi.Pod ) {
385442 volume := "secret-wrapper"
386443 dir := "/tmp/secret-wrapper"
0 commit comments