-
Notifications
You must be signed in to change notification settings - Fork 250
/
promotion.go
155 lines (133 loc) · 5.35 KB
/
promotion.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
152
153
154
155
package api
import (
"fmt"
"strings"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/sets"
)
type OKDInclusion bool
const (
okdPromotionNamespace = "origin"
ocpPromotionNamespace = "ocp"
WithOKD OKDInclusion = true
WithoutOKD OKDInclusion = false
PromotionStepName = "promotion"
PromotionQuayStepName = "promotion-quay"
)
// PromotionTargets adapts the single-target configuration to the multi-target paradigm.
// This function will be removed when the previous implementation is removed.
func PromotionTargets(c *PromotionConfiguration) []PromotionTarget {
if c == nil {
return nil
}
return c.Targets
}
// ImageTargets returns image targets
func ImageTargets(c *ReleaseBuildConfiguration) sets.Set[string] {
imageTargets := sets.New[string]()
for _, target := range PromotionTargets(c.PromotionConfiguration) {
for additional := range target.AdditionalImages {
imageTargets.Insert(target.AdditionalImages[additional])
}
}
if len(c.Images) > 0 || imageTargets.Len() > 0 {
imageTargets.Insert("[images]")
}
return imageTargets
}
// PromotesOfficialImages determines if a configuration will result in official images
// being promoted. This is a proxy for determining if a configuration contributes to
// the release payload.
func PromotesOfficialImages(configSpec *ReleaseBuildConfiguration, includeOKD OKDInclusion) bool {
for _, target := range PromotionTargets(configSpec.PromotionConfiguration) {
if !target.Disabled && BuildsOfficialImages(target, includeOKD) {
return true
}
}
return false
}
// PromotesOfficialImage determines if a configuration will promote promotionName
// and if it belongs to any official stream.
func PromotesOfficialImage(configSpec *ReleaseBuildConfiguration, includeOKD OKDInclusion, promotionName string) bool {
for _, target := range PromotionTargets(configSpec.PromotionConfiguration) {
if !target.Disabled && BuildsOfficialImages(target, includeOKD) && target.Name == promotionName {
return true
}
}
return false
}
// BuildsOfficialImages determines if a configuration will result in official images
// being built.
func BuildsOfficialImages(configSpec PromotionTarget, includeOKD OKDInclusion) bool {
return RefersToOfficialImage(configSpec.Namespace, includeOKD)
}
// BuildsAnyOfficialImages determines if a configuration will result in official images
// being built.
func BuildsAnyOfficialImages(configSpec *ReleaseBuildConfiguration, includeOKD OKDInclusion) bool {
var buildsAny bool
for _, target := range PromotionTargets(configSpec.PromotionConfiguration) {
buildsAny = buildsAny || BuildsOfficialImages(target, includeOKD)
}
return buildsAny
}
// RefersToOfficialImage determines if an image is official
func RefersToOfficialImage(namespace string, includeOKD OKDInclusion) bool {
return (bool(includeOKD) && namespace == okdPromotionNamespace) || namespace == ocpPromotionNamespace
}
func tagsInQuay(image string, tag ImageStreamTagReference, date string) ([]string, error) {
if date == "" {
return nil, fmt.Errorf("date must not be empty")
}
splits := strings.Split(image, "@sha256:")
if len(splits) != 2 {
return nil, fmt.Errorf("malformed image pull spec: %s", image)
}
digest := splits[1]
return []string{
QuayImageFromDateAndDigest(date, digest),
QuayImage(tag),
}, nil
}
// QuayImage returns the image in quay.io for an image stream tag which is used to push the image
func QuayImage(tag ImageStreamTagReference) string {
return fmt.Sprintf("%s:%s_%s_%s", QuayOpenShiftCIRepo, tag.Namespace, tag.Name, tag.Tag)
}
// QuayImageReference returns the image in quay.io for an image stream tag which is used to pull the image
func QuayImageReference(tag ImageStreamTagReference) string {
return strings.Replace(QuayImage(tag), "quay.io", QCIAPPCIDomain, 1)
}
// QuayImageFromDateAndDigest returns the image in quay.io for a date and an image digest which is used to push the image
func QuayImageFromDateAndDigest(date, digest string) string {
return fmt.Sprintf("%s:%s_sha256_%s", QuayOpenShiftCIRepo, date, digest)
}
var (
// DefaultMirrorFunc is the default mirroring function
DefaultMirrorFunc = func(source, target string, _ ImageStreamTagReference, _ string, mirror map[string]string) {
mirror[target] = source
}
// QuayMirrorFunc is the mirroring function for quay.io
QuayMirrorFunc = func(source, target string, tag ImageStreamTagReference, date string, mirror map[string]string) {
if quayTags, err := tagsInQuay(source, tag, date); err != nil {
logrus.WithField("source", source).WithError(err).
Warn("Failed to get the tag in quay.io and skipped the promotion to quay for this image")
} else {
for _, quayTag := range quayTags {
mirror[quayTag] = source
}
}
}
// DefaultTargetNameFunc is the default target name function
DefaultTargetNameFunc = func(registry string, config PromotionTarget) string {
if len(config.Name) > 0 {
return fmt.Sprintf("%s/%s/%s:${component}", registry, config.Namespace, config.Name)
}
return fmt.Sprintf("%s/%s/${component}:%s", registry, config.Namespace, config.Tag)
}
// QuayTargetNameFunc is the target name function for quay.io
QuayTargetNameFunc = func(_ string, config PromotionTarget) string {
if len(config.Name) > 0 {
return fmt.Sprintf("%s:%s_%s_${component}", QuayOpenShiftCIRepo, config.Namespace, config.Name)
}
return fmt.Sprintf("%s:%s_${component}_%s", QuayOpenShiftCIRepo, config.Namespace, config.Tag)
}
)