github.com/argoproj-labs/argocd-operator@v0.10.0/controllers/argocd/testing.go (about) 1 // Copyright 2020 ArgoCD Operator Developers 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package argocd 16 17 import ( 18 "context" 19 "sort" 20 "testing" 21 22 "github.com/go-logr/logr" 23 24 "github.com/argoproj-labs/argocd-operator/common" 25 26 "github.com/stretchr/testify/assert" 27 appsv1 "k8s.io/api/apps/v1" 28 corev1 "k8s.io/api/core/v1" 29 v1 "k8s.io/api/rbac/v1" 30 resourcev1 "k8s.io/apimachinery/pkg/api/resource" 31 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 32 "k8s.io/apimachinery/pkg/runtime" 33 "k8s.io/client-go/kubernetes/scheme" 34 "sigs.k8s.io/controller-runtime/pkg/client" 35 "sigs.k8s.io/controller-runtime/pkg/client/fake" 36 "sigs.k8s.io/controller-runtime/pkg/log/zap" 37 38 "github.com/argoproj-labs/argocd-operator/controllers/argoutil" 39 40 argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1" 41 ) 42 43 const ( 44 testNamespace = "argocd" 45 testArgoCDName = "argocd" 46 testApplicationController = "argocd-application-controller" 47 ) 48 49 func ZapLogger(development bool) logr.Logger { 50 return zap.New(zap.UseDevMode(development)) 51 } 52 53 type SchemeOpt func(*runtime.Scheme) error 54 55 func makeTestReconciler(client client.Client, sch *runtime.Scheme) *ReconcileArgoCD { 56 return &ReconcileArgoCD{ 57 Client: client, 58 Scheme: sch, 59 } 60 } 61 62 func makeTestReconcilerClient(sch *runtime.Scheme, resObjs, subresObjs []client.Object, runtimeObj []runtime.Object) client.Client { 63 client := fake.NewClientBuilder().WithScheme(sch) 64 if len(resObjs) > 0 { 65 client = client.WithObjects(resObjs...) 66 } 67 if len(subresObjs) > 0 { 68 client = client.WithStatusSubresource(subresObjs...) 69 } 70 if len(runtimeObj) > 0 { 71 client = client.WithRuntimeObjects(runtimeObj...) 72 } 73 return client.Build() 74 } 75 76 func makeTestReconcilerScheme(sOpts ...SchemeOpt) *runtime.Scheme { 77 s := scheme.Scheme 78 for _, opt := range sOpts { 79 _ = opt(s) 80 } 81 82 return s 83 } 84 85 type argoCDOpt func(*argoproj.ArgoCD) 86 87 func makeTestArgoCD(opts ...argoCDOpt) *argoproj.ArgoCD { 88 a := &argoproj.ArgoCD{ 89 ObjectMeta: metav1.ObjectMeta{ 90 Name: testArgoCDName, 91 Namespace: testNamespace, 92 }, 93 } 94 for _, o := range opts { 95 o(a) 96 } 97 return a 98 } 99 100 func makeTestArgoCDForKeycloak() *argoproj.ArgoCD { 101 a := &argoproj.ArgoCD{ 102 ObjectMeta: metav1.ObjectMeta{ 103 Name: testArgoCDName, 104 Namespace: testNamespace, 105 }, 106 Spec: argoproj.ArgoCDSpec{ 107 SSO: &argoproj.ArgoCDSSOSpec{ 108 Provider: "keycloak", 109 }, 110 Server: argoproj.ArgoCDServerSpec{ 111 Route: argoproj.ArgoCDRouteSpec{ 112 Enabled: true, 113 }, 114 }, 115 }, 116 } 117 return a 118 } 119 120 func makeTestArgoCDWithResources(opts ...argoCDOpt) *argoproj.ArgoCD { 121 a := &argoproj.ArgoCD{ 122 ObjectMeta: metav1.ObjectMeta{ 123 Name: testArgoCDName, 124 Namespace: testNamespace, 125 }, 126 Spec: argoproj.ArgoCDSpec{ 127 ApplicationSet: &argoproj.ArgoCDApplicationSet{ 128 Resources: makeTestApplicationSetResources(), 129 }, 130 HA: argoproj.ArgoCDHASpec{ 131 Resources: makeTestHAResources(), 132 }, 133 SSO: &argoproj.ArgoCDSSOSpec{ 134 Provider: "dex", 135 Dex: &argoproj.ArgoCDDexSpec{ 136 Resources: makeTestDexResources(), 137 }, 138 }, 139 Controller: argoproj.ArgoCDApplicationControllerSpec{ 140 Resources: makeTestControllerResources(), 141 }, 142 }, 143 } 144 for _, o := range opts { 145 o(a) 146 } 147 return a 148 } 149 150 func makeTestClusterRole() *v1.ClusterRole { 151 return &v1.ClusterRole{ 152 ObjectMeta: metav1.ObjectMeta{ 153 Name: testApplicationController, 154 Namespace: testNamespace, 155 }, 156 Rules: makeTestPolicyRules(), 157 } 158 } 159 160 func makeTestDeployment() *appsv1.Deployment { 161 var replicas int32 = 1 162 return &appsv1.Deployment{ 163 ObjectMeta: metav1.ObjectMeta{ 164 Name: testApplicationController, 165 Namespace: testNamespace, 166 }, 167 Spec: appsv1.DeploymentSpec{ 168 Replicas: &replicas, 169 Selector: &metav1.LabelSelector{ 170 MatchLabels: map[string]string{ 171 "app": "name", 172 }, 173 }, 174 Template: corev1.PodTemplateSpec{ 175 Spec: corev1.PodSpec{ 176 Containers: []corev1.Container{ 177 { 178 Command: []string{"testing"}, 179 Image: "test-image", 180 }, 181 }, 182 }, 183 }, 184 }, 185 } 186 } 187 188 func makeTestPolicyRules() []v1.PolicyRule { 189 return []v1.PolicyRule{ 190 { 191 APIGroups: []string{ 192 "foo.example.com", 193 }, 194 Resources: []string{ 195 "*", 196 }, 197 Verbs: []string{ 198 "*", 199 }, 200 }, 201 } 202 } 203 204 func initialCerts(t *testing.T, host string) argoCDOpt { 205 t.Helper() 206 return func(a *argoproj.ArgoCD) { 207 key, err := argoutil.NewPrivateKey() 208 assert.NoError(t, err) 209 cert, err := argoutil.NewSelfSignedCACertificate(a.Name, key) 210 assert.NoError(t, err) 211 encoded := argoutil.EncodeCertificatePEM(cert) 212 213 a.Spec.TLS.InitialCerts = map[string]string{ 214 host: string(encoded), 215 } 216 } 217 } 218 219 func stringMapKeys(m map[string]string) []string { 220 r := []string{} 221 for k := range m { 222 r = append(r, k) 223 } 224 sort.Strings(r) 225 return r 226 } 227 228 func makeTestControllerResources() *corev1.ResourceRequirements { 229 return &corev1.ResourceRequirements{ 230 Requests: corev1.ResourceList{ 231 corev1.ResourceMemory: resourcev1.MustParse("1024Mi"), 232 corev1.ResourceCPU: resourcev1.MustParse("1000m"), 233 }, 234 Limits: corev1.ResourceList{ 235 corev1.ResourceMemory: resourcev1.MustParse("2048Mi"), 236 corev1.ResourceCPU: resourcev1.MustParse("2000m"), 237 }, 238 } 239 } 240 241 func makeTestApplicationSetResources() *corev1.ResourceRequirements { 242 return &corev1.ResourceRequirements{ 243 Requests: corev1.ResourceList{ 244 corev1.ResourceMemory: resourcev1.MustParse("1024Mi"), 245 corev1.ResourceCPU: resourcev1.MustParse("1"), 246 }, 247 Limits: corev1.ResourceList{ 248 corev1.ResourceMemory: resourcev1.MustParse("2048Mi"), 249 corev1.ResourceCPU: resourcev1.MustParse("2"), 250 }, 251 } 252 } 253 254 func makeTestHAResources() *corev1.ResourceRequirements { 255 return &corev1.ResourceRequirements{ 256 Requests: corev1.ResourceList{ 257 corev1.ResourceMemory: resourcev1.MustParse("128Mi"), 258 corev1.ResourceCPU: resourcev1.MustParse("250m"), 259 }, 260 Limits: corev1.ResourceList{ 261 corev1.ResourceMemory: resourcev1.MustParse("256Mi"), 262 corev1.ResourceCPU: resourcev1.MustParse("500m"), 263 }, 264 } 265 } 266 267 func makeTestDexResources() *corev1.ResourceRequirements { 268 return &corev1.ResourceRequirements{ 269 Requests: corev1.ResourceList{ 270 corev1.ResourceMemory: resourcev1.MustParse("128Mi"), 271 corev1.ResourceCPU: resourcev1.MustParse("250m"), 272 }, 273 Limits: corev1.ResourceList{ 274 corev1.ResourceMemory: resourcev1.MustParse("256Mi"), 275 corev1.ResourceCPU: resourcev1.MustParse("500m"), 276 }, 277 } 278 } 279 280 func createNamespace(r *ReconcileArgoCD, n string, managedBy string) error { 281 ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: n}} 282 if managedBy != "" { 283 ns.Labels = map[string]string{common.ArgoCDManagedByLabel: managedBy} 284 } 285 286 if r.ManagedNamespaces == nil { 287 r.ManagedNamespaces = &corev1.NamespaceList{} 288 } 289 r.ManagedNamespaces.Items = append(r.ManagedNamespaces.Items, *ns) 290 291 return r.Client.Create(context.TODO(), ns) 292 } 293 294 func createNamespaceManagedByClusterArgoCDLabel(r *ReconcileArgoCD, n string, managedBy string) error { 295 ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: n}} 296 if managedBy != "" { 297 ns.Labels = map[string]string{common.ArgoCDManagedByClusterArgoCDLabel: managedBy} 298 } 299 300 if r.ManagedSourceNamespaces == nil { 301 r.ManagedSourceNamespaces = make(map[string]string) 302 } 303 r.ManagedSourceNamespaces[ns.Name] = "" 304 305 return r.Client.Create(context.TODO(), ns) 306 } 307 308 func merge(base map[string]string, diff map[string]string) map[string]string { 309 result := make(map[string]string) 310 311 for k, v := range base { 312 result[k] = v 313 } 314 for k, v := range diff { 315 result[k] = v 316 } 317 318 return result 319 }