@@ -3,22 +3,27 @@ package catalog
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "strings"
6
7
7
- "k8s.io/client-go/dynamic "
8
- "k8s.io/client-go/tools/cache "
8
+ "github.com/pkg/errors "
9
+ "github.com/sirupsen/logrus "
9
10
10
- "github.com/operator-framework/api/pkg/operators/v1alpha1"
11
- crdlib "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/crd"
12
- "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
13
- errorwrap "github.com/pkg/errors"
14
- logger "github.com/sirupsen/logrus"
15
11
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
16
12
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
17
13
apiextensionsv1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
18
14
apiextensionsv1beta1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
19
-
20
15
k8serrors "k8s.io/apimachinery/pkg/api/errors"
21
16
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
18
+ "k8s.io/apimachinery/pkg/util/yaml"
19
+ "k8s.io/client-go/dynamic"
20
+ "k8s.io/client-go/tools/cache"
21
+
22
+ "github.com/operator-framework/api/pkg/operators/v1alpha1"
23
+ listersv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1"
24
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/internal/alongside"
25
+ crdlib "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/crd"
26
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
22
27
)
23
28
24
29
// Stepper manages cluster interactions based on the step.
@@ -36,16 +41,22 @@ func (s StepperFunc) Status() (v1alpha1.StepStatus, error) {
36
41
// Builder holds clients and data structures required for the StepBuilder to work
37
42
// Builder attributes are not to meant to be accessed outside the StepBuilder method
38
43
type builder struct {
44
+ plan * v1alpha1.InstallPlan
45
+ csvLister listersv1alpha1.ClusterServiceVersionLister
39
46
opclient operatorclient.ClientInterface
40
47
dynamicClient dynamic.Interface
41
48
manifestResolver ManifestResolver
42
49
csvToProvidedAPIs map [string ]cache.Indexer
43
- logger logger.FieldLogger
50
+ logger logrus.FieldLogger
51
+
52
+ annotator alongside.Annotator
44
53
}
45
54
46
- func newBuilder (opclient operatorclient.ClientInterface , dynamicClient dynamic.Interface , csvToProvidedAPIs map [string ]cache.Indexer ,
47
- manifestResolver ManifestResolver , logger logger .FieldLogger ) * builder {
55
+ func newBuilder (plan * v1alpha1. InstallPlan , csvLister listersv1alpha1. ClusterServiceVersionLister , opclient operatorclient.ClientInterface , dynamicClient dynamic.Interface , csvToProvidedAPIs map [string ]cache.Indexer ,
56
+ manifestResolver ManifestResolver , logger logrus .FieldLogger ) * builder {
48
57
return & builder {
58
+ plan : plan ,
59
+ csvLister : csvLister ,
49
60
opclient : opclient ,
50
61
dynamicClient : dynamicClient ,
51
62
manifestResolver : manifestResolver ,
@@ -62,6 +73,29 @@ func (n notSupportedStepperErr) Error() string {
62
73
return n .message
63
74
}
64
75
76
+ func setInstalledAlongsideAnnotation (a alongside.Annotator , o metav1.Object , namespace string , name string , lister listersv1alpha1.ClusterServiceVersionLister ) {
77
+ var (
78
+ nns []alongside.NamespacedName
79
+ )
80
+
81
+ // Only keep references to existing and non-copied CSVs to
82
+ // avoid unbounded growth.
83
+ for _ , nn := range a .FromObject (o ) {
84
+ if csv , err := lister .ClusterServiceVersions (nn .Namespace ).Get (nn .Name ); k8serrors .IsNotFound (err ) {
85
+ continue
86
+ } else if err == nil && csv .IsCopied () {
87
+ continue
88
+ }
89
+ // CSV exists and is not copied OR err is non-nil, but
90
+ // not 404. Safer to assume it exists in unhandled
91
+ // error cases and try again next time.
92
+ nns = append (nns , nn )
93
+ }
94
+ nns = append (nns , alongside.NamespacedName {Namespace : namespace , Name : name })
95
+
96
+ a .ToObject (o , nns )
97
+ }
98
+
65
99
// step is a factory that creates StepperFuncs based on the install plan step Kind.
66
100
func (b * builder ) create (step v1alpha1.Step ) (Stepper , error ) {
67
101
manifest , err := b .manifestResolver .ManifestForStep (& step )
@@ -75,6 +109,20 @@ func (b *builder) create(step v1alpha1.Step) (Stepper, error) {
75
109
if err != nil {
76
110
return nil , err
77
111
}
112
+
113
+ if step .Resolving != "" {
114
+ var u unstructured.Unstructured
115
+ if err := yaml .NewYAMLOrJSONDecoder (strings .NewReader (manifest ), 32 ).Decode (& u ); err != nil {
116
+ return nil , err
117
+ }
118
+ setInstalledAlongsideAnnotation (b .annotator , & u , b .plan .GetNamespace (), step .Resolving , b .csvLister )
119
+ if b , err := u .MarshalJSON (); err != nil {
120
+ return nil , err
121
+ } else {
122
+ manifest = string (b )
123
+ }
124
+ }
125
+
78
126
switch version {
79
127
case crdlib .V1Version :
80
128
return b .NewCRDV1Step (b .opclient .ApiextensionsInterface ().ApiextensionsV1 (), & step , manifest ), nil
@@ -98,7 +146,7 @@ func (b *builder) NewCRDV1Step(client apiextensionsv1client.ApiextensionsV1Inter
98
146
if k8serrors .IsNotFound (err ) {
99
147
return v1alpha1 .StepStatusNotPresent , nil
100
148
} else {
101
- return v1alpha1 .StepStatusNotPresent , errorwrap .Wrapf (err , "error finding the %s CRD" , crd .Name )
149
+ return v1alpha1 .StepStatusNotPresent , errors .Wrapf (err , "error finding the %s CRD" , crd .Name )
102
150
}
103
151
}
104
152
established , namesAccepted := false , false
@@ -128,23 +176,23 @@ func (b *builder) NewCRDV1Step(client apiextensionsv1client.ApiextensionsV1Inter
128
176
currentCRD , _ := client .CustomResourceDefinitions ().Get (context .TODO (), crd .GetName (), metav1.GetOptions {})
129
177
crd .SetResourceVersion (currentCRD .GetResourceVersion ())
130
178
if err = validateV1CRDCompatibility (b .dynamicClient , currentCRD , crd ); err != nil {
131
- return v1alpha1 .StepStatusUnknown , errorwrap .Wrapf (err , "error validating existing CRs against new CRD's schema: %s" , step .Resource .Name )
179
+ return v1alpha1 .StepStatusUnknown , errors .Wrapf (err , "error validating existing CRs against new CRD's schema: %s" , step .Resource .Name )
132
180
}
133
181
134
182
// check to see if stored versions changed and whether the upgrade could cause potential data loss
135
183
safe , err := crdlib .SafeStorageVersionUpgrade (currentCRD , crd )
136
184
if ! safe {
137
185
b .logger .Errorf ("risk of data loss updating %s: %s" , step .Resource .Name , err )
138
- return v1alpha1 .StepStatusUnknown , errorwrap .Wrapf (err , "risk of data loss updating %s" , step .Resource .Name )
186
+ return v1alpha1 .StepStatusUnknown , errors .Wrapf (err , "risk of data loss updating %s" , step .Resource .Name )
139
187
}
140
188
if err != nil {
141
- return v1alpha1 .StepStatusUnknown , errorwrap .Wrapf (err , "checking CRD for potential data loss updating %s" , step .Resource .Name )
189
+ return v1alpha1 .StepStatusUnknown , errors .Wrapf (err , "checking CRD for potential data loss updating %s" , step .Resource .Name )
142
190
}
143
191
144
192
// Update CRD to new version
145
193
_ , err = client .CustomResourceDefinitions ().Update (context .TODO (), crd , metav1.UpdateOptions {})
146
194
if err != nil {
147
- return v1alpha1 .StepStatusUnknown , errorwrap .Wrapf (err , "error updating CRD: %s" , step .Resource .Name )
195
+ return v1alpha1 .StepStatusUnknown , errors .Wrapf (err , "error updating CRD: %s" , step .Resource .Name )
148
196
}
149
197
// If it already existed, mark the step as Present.
150
198
// they were equal - mark CRD as present
@@ -173,7 +221,7 @@ func (b *builder) NewCRDV1Beta1Step(client apiextensionsv1beta1client.Apiextensi
173
221
if k8serrors .IsNotFound (err ) {
174
222
return v1alpha1 .StepStatusNotPresent , nil
175
223
} else {
176
- return v1alpha1 .StepStatusNotPresent , errorwrap .Wrapf (err , "error finding the %s CRD" , crd .Name )
224
+ return v1alpha1 .StepStatusNotPresent , errors .Wrapf (err , "error finding the %s CRD" , crd .Name )
177
225
}
178
226
}
179
227
established , namesAccepted := false , false
@@ -204,23 +252,23 @@ func (b *builder) NewCRDV1Beta1Step(client apiextensionsv1beta1client.Apiextensi
204
252
crd .SetResourceVersion (currentCRD .GetResourceVersion ())
205
253
206
254
if err = validateV1Beta1CRDCompatibility (b .dynamicClient , currentCRD , crd ); err != nil {
207
- return v1alpha1 .StepStatusUnknown , errorwrap .Wrapf (err , "error validating existing CRs against new CRD's schema: %s" , step .Resource .Name )
255
+ return v1alpha1 .StepStatusUnknown , errors .Wrapf (err , "error validating existing CRs against new CRD's schema: %s" , step .Resource .Name )
208
256
}
209
257
210
258
// check to see if stored versions changed and whether the upgrade could cause potential data loss
211
259
safe , err := crdlib .SafeStorageVersionUpgrade (currentCRD , crd )
212
260
if ! safe {
213
261
b .logger .Errorf ("risk of data loss updating %s: %s" , step .Resource .Name , err )
214
- return v1alpha1 .StepStatusUnknown , errorwrap .Wrapf (err , "risk of data loss updating %s" , step .Resource .Name )
262
+ return v1alpha1 .StepStatusUnknown , errors .Wrapf (err , "risk of data loss updating %s" , step .Resource .Name )
215
263
}
216
264
if err != nil {
217
- return v1alpha1 .StepStatusUnknown , errorwrap .Wrapf (err , "checking CRD for potential data loss updating %s" , step .Resource .Name )
265
+ return v1alpha1 .StepStatusUnknown , errors .Wrapf (err , "checking CRD for potential data loss updating %s" , step .Resource .Name )
218
266
}
219
267
220
268
// Update CRD to new version
221
269
_ , err = client .CustomResourceDefinitions ().Update (context .TODO (), crd , metav1.UpdateOptions {})
222
270
if err != nil {
223
- return v1alpha1 .StepStatusUnknown , errorwrap .Wrapf (err , "error updating CRD: %s" , step .Resource .Name )
271
+ return v1alpha1 .StepStatusUnknown , errors .Wrapf (err , "error updating CRD: %s" , step .Resource .Name )
224
272
}
225
273
// If it already existed, mark the step as Present.
226
274
// they were equal - mark CRD as present
0 commit comments