1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package preflight
16
17 import (
18 "context"
19 "fmt"
20 "log"
21 "testing"
22
23 "github.com/GoogleCloudPlatform/k8s-config-connector/operator/pkg/manifest"
24 "github.com/GoogleCloudPlatform/k8s-config-connector/operator/pkg/test/util/asserts"
25 corev1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/client-go/kubernetes/scheme"
28 "k8s.io/client-go/rest"
29 "sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/addon/pkg/loaders"
30 "sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative"
31 "sigs.k8s.io/kubebuilder-declarative-pattern/pkg/test/mocks"
32
33 corev1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/operator/pkg/apis/core/v1beta1"
34 "github.com/GoogleCloudPlatform/k8s-config-connector/operator/pkg/k8s"
35 )
36
37 var (
38 cfg *rest.Config
39 )
40
41 func init() {
42 s := scheme.Scheme
43 if err := corev1beta1.SchemeBuilder.AddToScheme(s); err != nil {
44 log.Fatalf("error registering core kcc operator scheme: %v", err)
45 }
46 }
47
48 type FakeRepo struct {
49 channel *loaders.Channel
50 }
51
52 var _ manifest.Repository = &FakeRepo{}
53
54 func (r *FakeRepo) LoadManifest(ctx context.Context, component string, id string, o declarative.DeclarativeObject) (map[string]string, error) {
55 panic("implement me")
56 }
57
58 func (r *FakeRepo) LoadChannel(ctx context.Context, name string) (*loaders.Channel, error) {
59 return r.channel, nil
60 }
61
62 func (r *FakeRepo) LoadNamespacedComponents(ctx context.Context, componentName string, version string) (map[string]string, error) {
63 panic("implement me")
64 }
65
66 func TestUpgradeChecker_Preflight(t *testing.T) {
67 t.Parallel()
68 curTime := metav1.Now()
69 testConfigConnector := &corev1beta1.ConfigConnector{
70 ObjectMeta: metav1.ObjectMeta{
71 Name: "test-configconnector",
72 },
73 Spec: corev1beta1.ConfigConnectorSpec{
74 GoogleServiceAccount: "foo@bar.iam.gserviceaccount.com",
75 },
76 }
77 tests := []struct {
78 name string
79 cc *corev1beta1.ConfigConnector
80 ns *corev1.Namespace
81 channel *loaders.Channel
82 err error
83 delete bool
84 }{
85 {
86 name: "no existing instance, can upgrade/deploy the new version",
87 cc: testConfigConnector,
88 channel: nil,
89 ns: nil,
90 err: nil,
91 },
92 {
93 name: "new version is compatible, can upgrade it",
94 cc: testConfigConnector,
95 ns: &corev1.Namespace{
96 ObjectMeta: metav1.ObjectMeta{
97 Name: k8s.CNRMSystemNamespace,
98 Annotations: map[string]string{
99 k8s.VersionAnnotation: "1.2.3",
100 },
101 },
102 },
103 channel: &loaders.Channel{
104 Manifests: []loaders.Version{
105 {
106 Package: "configconnector",
107 Version: "1.4.0",
108 },
109 },
110 },
111 err: nil,
112 },
113 {
114 name: "reconcile on the same version",
115 cc: testConfigConnector,
116 ns: &corev1.Namespace{
117 ObjectMeta: metav1.ObjectMeta{
118 Name: k8s.CNRMSystemNamespace,
119 Annotations: map[string]string{
120 k8s.VersionAnnotation: "1.2.3",
121 },
122 },
123 },
124 channel: &loaders.Channel{
125 Manifests: []loaders.Version{
126 {
127 Package: "configconnector",
128 Version: "1.2.3",
129 },
130 },
131 },
132 err: nil,
133 },
134 {
135 name: "major change, no upgrade",
136 cc: testConfigConnector,
137 ns: &corev1.Namespace{
138 ObjectMeta: metav1.ObjectMeta{
139 Name: k8s.CNRMSystemNamespace,
140 Annotations: map[string]string{
141 k8s.VersionAnnotation: "1.2.3",
142 },
143 },
144 },
145 channel: &loaders.Channel{
146 Manifests: []loaders.Version{
147 {
148 Package: "configconnector",
149 Version: "2.0.0",
150 },
151 },
152 },
153 err: fmt.Errorf("incompatible version"),
154 },
155 {
156 name: "major change, no downgrade",
157 cc: testConfigConnector,
158 ns: &corev1.Namespace{
159 ObjectMeta: metav1.ObjectMeta{
160 Name: k8s.CNRMSystemNamespace,
161 Annotations: map[string]string{
162 k8s.VersionAnnotation: "2.0.0",
163 },
164 },
165 },
166 channel: &loaders.Channel{
167 Manifests: []loaders.Version{
168 {
169 Package: "configconnector",
170 Version: "1.2.0",
171 },
172 },
173 },
174 err: fmt.Errorf("incompatible version"),
175 },
176 {
177 name: "delete will always pass preflight check",
178 cc: &corev1beta1.ConfigConnector{
179 ObjectMeta: metav1.ObjectMeta{
180 Name: "test-configconnector",
181 DeletionTimestamp: &curTime,
182 },
183 Spec: corev1beta1.ConfigConnectorSpec{
184 GoogleServiceAccount: "foo@bar.iam.gserviceaccount.com",
185 },
186 },
187 ns: &corev1.Namespace{
188 ObjectMeta: metav1.ObjectMeta{
189 Name: k8s.CNRMSystemNamespace,
190 Annotations: map[string]string{
191 k8s.VersionAnnotation: "1.2.3",
192 },
193 },
194 },
195 channel: &loaders.Channel{
196 Manifests: []loaders.Version{
197 {
198 Package: "configconnector",
199 Version: "2.0.0",
200 },
201 },
202 },
203 err: nil,
204 },
205 }
206
207 for _, tc := range tests {
208 tc := tc
209 t.Run(tc.name, func(t *testing.T) {
210 t.Parallel()
211 mgr := mocks.Manager{}
212 ctx := context.Background()
213 client := mgr.GetClient()
214 if err := client.Create(ctx, tc.cc); err != nil {
215 t.Fatalf("error creating %v %v: %v", tc.cc.Kind, tc.cc.Name, err)
216 }
217 if tc.ns != nil {
218 if err := client.Create(ctx, tc.ns); err != nil {
219 t.Fatalf("error creating %v %v: %v", tc.ns.Kind, tc.cc.Name, err)
220 }
221 }
222 repo := FakeRepo{
223 channel: tc.channel,
224 }
225 u := NewUpgradeChecker(client, &repo)
226 err := u.Preflight(ctx, tc.cc)
227 asserts.AssertErrorIsExpected(t, err, tc.err)
228 })
229 }
230 }
231
View as plain text