-
Notifications
You must be signed in to change notification settings - Fork 249
/
input_image_tag.go
151 lines (127 loc) · 4.94 KB
/
input_image_tag.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package steps
import (
"context"
"fmt"
"github.com/sirupsen/logrus"
coreapi "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client"
imagev1 "github.com/openshift/api/image/v1"
"github.com/openshift/ci-tools/pkg/api"
"github.com/openshift/ci-tools/pkg/results"
"github.com/openshift/ci-tools/pkg/steps/loggingclient"
"github.com/openshift/ci-tools/pkg/steps/utils"
)
// inputImageTagStep will ensure that a tag exists
// in the pipeline ImageStream that resolves to
// the base image
type inputImageTagStep struct {
config *api.InputImageTagStepConfiguration
client loggingclient.LoggingClient
jobSpec *api.JobSpec
imageName string
}
func (s *inputImageTagStep) Inputs() (api.InputDefinition, error) {
if len(s.imageName) > 0 {
return api.InputDefinition{s.imageName}, nil
}
if api.IsCreatedForClusterBotJob(s.config.BaseImage.Namespace) {
from := imagev1.ImageStreamTag{}
namespace := s.config.BaseImage.Namespace
name := fmt.Sprintf("%s:%s", s.config.BaseImage.Name, s.config.BaseImage.Tag)
if err := s.client.Get(context.TODO(), ctrlruntimeclient.ObjectKey{
Namespace: namespace,
Name: name,
}, &from); err != nil {
return nil, fmt.Errorf("could not resolve base image from %s/%s: %w", namespace, name, err)
}
if len(s.config.Sources) > 0 {
logrus.Debugf("Resolved %s (%s) to %s.", s.config.BaseImage.ISTagName(), s.config.FormattedSources(), from.Image.Name)
} else {
logrus.Debugf("Resolved %s to %s.", s.config.BaseImage.ISTagName(), from.Image.Name)
}
s.imageName = from.Image.Name
} else {
imageName := api.QuayImageReference(s.config.BaseImage)
logrus.Debugf("Resolved %s to %s.", s.config.BaseImage.ISTagName(), imageName)
s.imageName = imageName
}
return api.InputDefinition{s.imageName}, nil
}
func (*inputImageTagStep) Validate() error { return nil }
func (s *inputImageTagStep) Run(ctx context.Context) error {
return results.ForReason("tagging_input_image").ForError(s.run(ctx))
}
func (s *inputImageTagStep) run(ctx context.Context) error {
logrus.Infof("Tagging %s into %s:%s.", s.config.BaseImage.ISTagName(), api.PipelineImageStream, s.config.To)
if _, err := s.Inputs(); err != nil {
return fmt.Errorf("could not resolve inputs for image tag step: %w", err)
}
from := &coreapi.ObjectReference{
Kind: "DockerImage",
Name: api.QuayImageReference(s.config.BaseImage),
}
if api.IsCreatedForClusterBotJob(s.config.BaseImage.Namespace) {
from = &coreapi.ObjectReference{
Kind: "ImageStreamImage",
Name: fmt.Sprintf("%s@%s", s.config.BaseImage.Name, s.imageName),
Namespace: s.config.BaseImage.Namespace,
}
}
ist := &imagev1.ImageStreamTag{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s:%s", api.PipelineImageStream, s.config.To),
Namespace: s.jobSpec.Namespace(),
},
Tag: &imagev1.TagReference{
ReferencePolicy: imagev1.TagReferencePolicy{
Type: imagev1.LocalTagReferencePolicy,
},
From: from,
ImportPolicy: imagev1.TagImportPolicy{
ImportMode: imagev1.ImportModePreserveOriginal,
},
},
}
if err := s.client.Create(ctx, ist); err != nil && !kerrors.IsAlreadyExists(err) {
return fmt.Errorf("failed to create imagestreamtag for input image: %w", err)
}
logrus.Debugf("Waiting to import tags on imagestream (after creating pipeline) %s/%s ...", s.jobSpec.Namespace(), api.PipelineImageStream)
if err := utils.WaitForImportingISTag(ctx, s.client, s.jobSpec.Namespace(), api.PipelineImageStream, nil, sets.New[string](), utils.DefaultImageImportTimeout); err != nil {
return fmt.Errorf("failed to wait for importing imagestreamtags on %s/%s: %w", s.jobSpec.Namespace(), api.PipelineImageStream, err)
}
logrus.Debugf("Imported tags on imagestream (after creating pipeline) %s/%s", s.jobSpec.Namespace(), api.PipelineImageStream)
return nil
}
func (s *inputImageTagStep) Requires() []api.StepLink {
return nil
}
func (s *inputImageTagStep) Creates() []api.StepLink {
return []api.StepLink{api.InternalImageLink(s.config.To)}
}
func (s *inputImageTagStep) Provides() api.ParameterMap {
tag := s.config.To
return api.ParameterMap{
utils.PipelineImageEnvFor(tag): utils.ImageDigestFor(s.client, s.jobSpec.Namespace, api.PipelineImageStream, string(tag)),
}
}
func (s *inputImageTagStep) Name() string { return s.config.TargetName() }
func (s *inputImageTagStep) Description() string {
return fmt.Sprintf("Find the input image %s and tag it into the pipeline", s.config.To)
}
func (s *inputImageTagStep) Objects() []ctrlruntimeclient.Object {
return s.client.Objects()
}
func InputImageTagStep(
config *api.InputImageTagStepConfiguration,
client loggingclient.LoggingClient,
jobSpec *api.JobSpec) api.Step {
// when source and destination client are the same, we don't need to use external imports
return &inputImageTagStep{
config: config,
client: client,
jobSpec: jobSpec,
}
}