7
7
"fmt"
8
8
"net"
9
9
"os"
10
+ "strconv"
10
11
"strings"
11
12
"time"
12
13
@@ -22,10 +23,13 @@ import (
22
23
"github.com/operator-framework/api/pkg/lib/version"
23
24
"github.com/operator-framework/api/pkg/operators/v1alpha1"
24
25
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
26
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalogtempate"
25
27
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry"
28
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/catalogsource"
26
29
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
27
30
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
28
31
"github.com/operator-framework/operator-lifecycle-manager/test/e2e/ctx"
32
+ "k8s.io/apimachinery/pkg/api/meta"
29
33
)
30
34
31
35
var _ = Describe ("Catalog represents a store of bundles which OLM can use to install Operators" , func () {
@@ -1028,6 +1032,138 @@ var _ = Describe("Catalog represents a store of bundles which OLM can use to ins
1028
1032
Expect (err ).ToNot (HaveOccurred ())
1029
1033
Expect (updatePods .Items ).To (HaveLen (0 ))
1030
1034
})
1035
+
1036
+ It ("adding catalog template adjusts image used" , func () {
1037
+ // This test attempts to create a catalog source, and update it with a template annotation
1038
+ // and ensure that the image gets changed according to what's in the template as well as
1039
+ // check the status conditions are updated accordingly
1040
+
1041
+ sourceName := genName ("catalog-" )
1042
+ source := & v1alpha1.CatalogSource {
1043
+ TypeMeta : metav1.TypeMeta {
1044
+ Kind : v1alpha1 .CatalogSourceKind ,
1045
+ APIVersion : v1alpha1 .CatalogSourceCRDAPIVersion ,
1046
+ },
1047
+ ObjectMeta : metav1.ObjectMeta {
1048
+ Name : sourceName ,
1049
+ Namespace : testNamespace ,
1050
+ Labels : map [string ]string {"olm.catalogSource" : sourceName },
1051
+ },
1052
+ Spec : v1alpha1.CatalogSourceSpec {
1053
+ SourceType : v1alpha1 .SourceTypeGrpc ,
1054
+ Image : "quay.io/olmtest/catsrc-update-test:old" ,
1055
+ },
1056
+ }
1057
+
1058
+ By ("creating a catalog source" )
1059
+ source , err := crc .OperatorsV1alpha1 ().CatalogSources (source .GetNamespace ()).Create (context .TODO (), source , metav1.CreateOptions {})
1060
+ Expect (err ).ToNot (HaveOccurred ())
1061
+
1062
+ configmap := corev1.ConfigMap {}
1063
+ configmapName := genName ("configmap-" )
1064
+ configmap .SetName (configmapName )
1065
+ configmap .SetNamespace (testNamespace )
1066
+ configmap .Data = map [string ]string {"test" : "mytest" }
1067
+
1068
+ By ("creating an arbitrary config map to be the source of a GVK template" )
1069
+ _ , err = c .KubernetesInterface ().CoreV1 ().ConfigMaps (testNamespace ).Create (context .TODO (), & configmap , metav1.CreateOptions {})
1070
+ Expect (err ).ShouldNot (HaveOccurred ())
1071
+
1072
+ defer func () {
1073
+ // cleanup
1074
+ err := crc .OperatorsV1alpha1 ().CatalogSources (testNamespace ).Delete (context .TODO (), sourceName , metav1.DeleteOptions {})
1075
+ Expect (err ).ShouldNot (HaveOccurred ())
1076
+
1077
+ err = c .KubernetesInterface ().CoreV1 ().ConfigMaps (testNamespace ).Delete (context .TODO (), configmapName , metav1.DeleteOptions {})
1078
+ Expect (err ).ShouldNot (HaveOccurred ())
1079
+
1080
+ }()
1081
+
1082
+ By ("update the catalog source with template annotation" )
1083
+ // create a gvk template to point at the configmap
1084
+ gvkTemplate := fmt .Sprintf ("{group:,version:v1,kind:ConfigMap,name:%s,namespace:%s,jsonpath:{.data.test}}" , configmapName , testNamespace )
1085
+
1086
+ source , err = crc .OperatorsV1alpha1 ().CatalogSources (source .GetNamespace ()).Get (context .TODO (), source .GetName (), metav1.GetOptions {})
1087
+ Expect (err ).ShouldNot (HaveOccurred (), "error getting catalog source" )
1088
+
1089
+ // create an annotation using the gvk and kube templates
1090
+ source .SetAnnotations (map [string ]string {catalogsource .CatalogImageTemplateAnnotation : fmt .Sprintf ("quay.io/olmtest/catsrc-update-test:%s-%s.%s.%s" , gvkTemplate , catalogsource .TEMPL_KUBEMAJORV , catalogsource .TEMPL_KUBEMINORV , catalogsource .TEMPL_KUBEPATCHV )})
1091
+
1092
+ source , err = crc .OperatorsV1alpha1 ().CatalogSources (source .GetNamespace ()).Update (context .TODO (), source , metav1.UpdateOptions {})
1093
+ Expect (err ).ShouldNot (HaveOccurred (), "error updating catalog source with template annotation" )
1094
+
1095
+ // wait for status condition to show up
1096
+ Eventually (func () (bool , error ) {
1097
+ source , err = crc .OperatorsV1alpha1 ().CatalogSources (source .GetNamespace ()).Get (context .TODO (), sourceName , metav1.GetOptions {})
1098
+ if err != nil {
1099
+ return false , err
1100
+ }
1101
+ // if the conditions array has the entry we know things got updated
1102
+ condition := meta .FindStatusCondition (source .Status .Conditions , catalogtempate .StatusTypeTemplatesHaveResolved )
1103
+ if condition != nil {
1104
+ return true , nil
1105
+ }
1106
+
1107
+ return false , nil
1108
+ }, 5 * time .Minute , 1 * time .Second ).Should (BeTrue ())
1109
+
1110
+ // source should be the latest we got from the eventually block
1111
+ Expect (source .Status .Conditions ).ToNot (BeNil ())
1112
+
1113
+ // the first time a GVK template is encountered, watches are setup for those resources so the
1114
+ // templates can't be resolved immediately. We should have status conditions and they should indicate
1115
+ // that resolution has not happened yet
1116
+ templatesResolvedCondition := meta .FindStatusCondition (source .Status .Conditions , catalogtempate .StatusTypeTemplatesHaveResolved )
1117
+ if Expect (templatesResolvedCondition ).ToNot (BeNil ()) {
1118
+ Expect (templatesResolvedCondition .Reason ).To (BeIdenticalTo (catalogtempate .ReasonUnableToResolve ))
1119
+ Expect (templatesResolvedCondition .Status ).To (BeIdenticalTo (metav1 .ConditionFalse ))
1120
+ }
1121
+ resolvedImageCondition := meta .FindStatusCondition (source .Status .Conditions , catalogtempate .StatusTypeResolvedImage )
1122
+ if Expect (resolvedImageCondition ).ToNot (BeNil ()) {
1123
+ Expect (resolvedImageCondition .Reason ).To (BeIdenticalTo (catalogtempate .ReasonUnableToResolve ))
1124
+ Expect (resolvedImageCondition .Status ).To (BeIdenticalTo (metav1 .ConditionFalse ))
1125
+ }
1126
+
1127
+ // update catalog source with annotation (to kick resync)
1128
+ source , err = crc .OperatorsV1alpha1 ().CatalogSources (source .GetNamespace ()).Get (context .TODO (), source .GetName (), metav1.GetOptions {})
1129
+ Expect (err ).ShouldNot (HaveOccurred (), "error getting catalog source pod" )
1130
+ source .Annotations ["testKey" ] = genName ("newValue" )
1131
+ _ , err = crc .OperatorsV1alpha1 ().CatalogSources (source .GetNamespace ()).Update (context .TODO (), source , metav1.UpdateOptions {})
1132
+ Expect (err ).ShouldNot (HaveOccurred (), "error updating catalog source pod with test annotation" )
1133
+
1134
+ // wait for change in status condition
1135
+ Eventually (func () (bool , error ) {
1136
+ source , err = crc .OperatorsV1alpha1 ().CatalogSources (source .GetNamespace ()).Get (context .TODO (), sourceName , metav1.GetOptions {})
1137
+ if err != nil {
1138
+ return false , err
1139
+ }
1140
+ // condition should flip to true indicating that the catalog image has been updated
1141
+ if meta .IsStatusConditionTrue (source .Status .Conditions , catalogtempate .StatusTypeTemplatesHaveResolved ) {
1142
+ return true , nil
1143
+ }
1144
+
1145
+ return false , nil
1146
+ }, 5 * time .Minute , 1 * time .Second ).Should (BeTrue ())
1147
+
1148
+ templatesResolvedCondition = meta .FindStatusCondition (source .Status .Conditions , catalogtempate .StatusTypeTemplatesHaveResolved )
1149
+ if Expect (templatesResolvedCondition ).ToNot (BeNil ()) {
1150
+ Expect (templatesResolvedCondition .Reason ).To (BeIdenticalTo (catalogtempate .ReasonAllTemplatesResolved ))
1151
+ Expect (templatesResolvedCondition .Status ).To (BeIdenticalTo (metav1 .ConditionTrue ))
1152
+ }
1153
+ resolvedImageCondition = meta .FindStatusCondition (source .Status .Conditions , catalogtempate .StatusTypeResolvedImage )
1154
+ if Expect (resolvedImageCondition ).ToNot (BeNil ()) {
1155
+ Expect (resolvedImageCondition .Reason ).To (BeIdenticalTo (catalogtempate .ReasonAllTemplatesResolved ))
1156
+ Expect (resolvedImageCondition .Status ).To (BeIdenticalTo (metav1 .ConditionTrue ))
1157
+
1158
+ // if we can, try to determine the server version so we can check the resulting image
1159
+ if serverVersion , err := crc .Discovery ().ServerVersion (); err != nil {
1160
+ if serverGitVersion , err := semver .Parse (serverVersion .GitVersion ); err != nil {
1161
+ expectedImage := fmt .Sprintf ("quay.io/olmtest/catsrc-update-test:mytest-%s.%s.%s" , serverVersion .Major , serverVersion .Minor , strconv .FormatUint (serverGitVersion .Patch , 10 ))
1162
+ Expect (resolvedImageCondition .Message ).To (BeIdenticalTo (expectedImage ))
1163
+ }
1164
+ }
1165
+ }
1166
+ })
1031
1167
})
1032
1168
1033
1169
const (
0 commit comments