|
|
|
/*
|
|
|
|
Copyright 2022 The Flux authors
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package build
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
|
|
|
|
"github.com/fluxcd/pkg/apis/meta"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
|
|
"sigs.k8s.io/kustomize/api/resource"
|
|
|
|
"sigs.k8s.io/kustomize/kyaml/yaml"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestTrimSopsData(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
name string
|
|
|
|
yamlStr string
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "secret with sops token",
|
|
|
|
yamlStr: `apiVersion: v1
|
|
|
|
kind: Secret
|
|
|
|
metadata:
|
|
|
|
name: my-secret
|
|
|
|
type: Opaque
|
|
|
|
data:
|
|
|
|
token: |
|
|
|
|
ewoJImRhdGEiOiAiRU5DW0FFUzI1Nl9HQ00sZGF0YTpvQmU1UGxQbWZRQ1VVYzRzcUtJbW
|
|
|
|
p3PT0saXY6TUxMRVcxNVFDOWtSZFZWYWdKbnpMQ1NrMHhaR1dJcEFlVGZIenl4VDEwZz0s
|
|
|
|
dGFnOkszR2tCQ0dTK3V0NFRwazZuZGIwQ0E9PSx0eXBlOnN0cl0iLAoJInNvcHMiOiB7Cg
|
|
|
|
kJImttcyI6IG51bGwsCgkJImdjcF9rbXMiOiBudWxsLAoJCSJhenVyZV9rdiI6IG51bGws
|
|
|
|
CgkJImhjX3ZhdWx0IjogbnVsbCwKCQkiYWdlIjogWwoJCQl7CgkJCQkicmVjaXBpZW50Ij
|
|
|
|
ogImFnZTEwbGEyZ2Uwd3R2eDNxcjdkYXRxZjdyczR5bmd4c3pkYWw5MjdmczlydWthbXI4
|
|
|
|
dTJwc2hzdnR6N2NlIiwKCQkJCSJlbmMiOiAiLS0tLS1CRUdJTiBBR0UgRU5DUllQVEVEIE
|
|
|
|
ZJTEUtLS0tLVxuWVdkbExXVnVZM0o1Y0hScGIyNHViM0puTDNZeENpMCtJRmd5TlRVeE9T
|
|
|
|
QTFMMlJwWkhScksxRlNWbVlyZDFWYVxuWTBoeFdGUXpTREJzVDFrM1dqTnRZbVUxUW1saW
|
|
|
|
FESnljWGxOQ25GMVlqZE5PVGhWYlZOdk1HOXJOUzlaVVhad1xuTW5WMGJuUlVNR050ZWpG
|
|
|
|
UGJ6TTRVMlV6V2tzemVWa0tMUzB0SUdKNlVHaHhNVVYzWW1WSlRIbEpTVUpwUlZSWlxuVm
|
|
|
|
pkMFJWUmFkVTh3ZWt4WFRISXJZVXBsWWtOMmFFRUswSS9NQ0V0WFJrK2IvTjJHMUpGM3ZI
|
|
|
|
UVQyNGRTaFdZRFxudytKSVVTQTNhTGYyc3YwenIyTWRVRWRWV0JKb004blQ0RDR4VmJCT1
|
|
|
|
JEKzY2OVcrOW5EZVN3PT1cbi0tLS0tRU5EIEFHRSBFTkNSWVBURUQgRklMRS0tLS0tXG4i
|
|
|
|
CgkJCX0KCQldLAoJCSJsYXN0bW9kaWZpZWQiOiAiMjAyMS0xMS0yNlQxNjozNDo1MVoiLA
|
|
|
|
oJCSJtYWMiOiAiRU5DW0FFUzI1Nl9HQ00sZGF0YTpDT0d6ZjVZQ0hOTlA2ejRKYUVLcmpO
|
|
|
|
M004ZjUrUTF1S1VLVE1Id2ozODgvSUNtTHlpMnNTclRtajdQUCtYN005alRWd2E4d1ZnWV
|
|
|
|
RwTkxpVkp4K0xjeHF2SVhNMFR5bysvQ3UxenJmYW85OGFpQUNQOCtUU0VEaUZRTnRFdXMy
|
|
|
|
M0grZC9YMWhxTXdSSERJM2tRKzZzY2dFR25xWTU3cjNSRFNBM0U4RWhIcjQ9LGl2Okx4aX
|
|
|
|
RWSVltOHNyWlZxRnVlSmg5bG9DbEE0NFkyWjNYQVZZbXhlc01tT2c9LHRhZzpZOHFGRDhV
|
|
|
|
R2xEZndOU3Y3eGxjbjZBPT0sdHlwZTpzdHJdIiwKCQkicGdwIjogbnVsbCwKCQkidW5lbm
|
|
|
|
NyeXB0ZWRfc3VmZml4IjogIl91bmVuY3J5cHRlZCIsCgkJInZlcnNpb24iOiAiMy43LjEi
|
|
|
|
Cgl9Cn0=
|
|
|
|
`,
|
|
|
|
expected: `apiVersion: v1
|
|
|
|
data:
|
|
|
|
token: KipTT1BTKio=
|
|
|
|
kind: Secret
|
|
|
|
metadata:
|
|
|
|
name: my-secret
|
|
|
|
type: Opaque
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "secret with basic auth",
|
|
|
|
yamlStr: `apiVersion: v1
|
|
|
|
data:
|
|
|
|
password: cGFzc3dvcmQK
|
|
|
|
username: YWRtaW4K
|
|
|
|
kind: Secret
|
|
|
|
metadata:
|
|
|
|
name: secret-basic-auth
|
|
|
|
type: kubernetes.io/basic-auth
|
|
|
|
`,
|
|
|
|
expected: `apiVersion: v1
|
|
|
|
data:
|
|
|
|
password: cGFzc3dvcmQK
|
|
|
|
username: YWRtaW4K
|
|
|
|
kind: Secret
|
|
|
|
metadata:
|
|
|
|
name: secret-basic-auth
|
|
|
|
type: kubernetes.io/basic-auth
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "secret sops secret",
|
|
|
|
yamlStr: `apiVersion: v1
|
|
|
|
data:
|
|
|
|
.dockerconfigjson: ENC[AES256_GCM,data:KHCFH3hNnc+PMfWLFEPjebf3W4z4WXbGFAANRZyZC+07z7wlrTALJM6rn8YslW4tMAWCoAYxblC5WRCszTy0h9rw0U/RGOv5H0qCgnNg/FILFUqhwo9pNfrUH+MEP4M9qxxbLKZwObpHUE7DUsKx1JYAxsI=,iv:q48lqUbUQD+0cbYcjNMZMJLRdGHi78ZmDhNAT2th9tg=,tag:QRI2SZZXQrAcdql3R5AH2g==,type:str]
|
|
|
|
kind: Secret
|
|
|
|
metadata:
|
|
|
|
name: secret
|
|
|
|
type: kubernetes.io/dockerconfigjson
|
|
|
|
sops:
|
|
|
|
kms: []
|
|
|
|
gcp_kms: []
|
|
|
|
azure_kv: []
|
|
|
|
hc_vault: []
|
|
|
|
age:
|
|
|
|
- recipient: age10la2ge0wtvx3qr7datqf7rs4yngxszdal927fs9rukamr8u2pshsvtz7ce
|
|
|
|
enc: |
|
|
|
|
-----BEGIN AGE ENCRYPTED FILE-----
|
|
|
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3eU1CTEJhVXZ4eEVYYkVV
|
|
|
|
OU90TEcrR2pYckttN0pBanJoSUZWSW1RQXlRCkUydFJ3V1NZUTBuVFF0aC9GUEcw
|
|
|
|
bUdhNjJWTkoyL1FUVi9Dc1dxUDBkM0UKLS0tIE1sQXkwcWdGaEFuY0RHQTVXM0J6
|
|
|
|
dWpJcThEbW15V3dXYXpPZklBdW1Hd1kKoIAdmGNPrEctV8h1w8KuvQ5S+BGmgqN9
|
|
|
|
MgpNmUhJjWhgcQpb5BRYpQesBOgU5TBGK7j58A6DMDKlSiYZsdQchQ==
|
|
|
|
-----END AGE ENCRYPTED FILE-----
|
|
|
|
lastmodified: "2022-02-03T16:03:17Z"
|
|
|
|
mac: ENC[AES256_GCM,data:AHdYSawajwgAFwlmDN1IPNmT9vWaYKzyVIra2d6sPcjTbZ8/p+VRSRpVm4XZFFsaNnW5AUJaouwXnKYDTmJDXKlr/rQcu9kXqsssQgdzcXaA6l5uJlgsnml8ba7J3OK+iEKMax23mwQEx2EUskCd9ENOwFDkunP02sxqDNOz20k=,iv:8F5OamHt3fAVorf6p+SoIrWoqkcATSGWVoM0EK87S4M=,tag:E1mxXnc7wWkEX5BxhpLtng==,type:str]
|
|
|
|
pgp: []
|
|
|
|
encrypted_regex: ^(data|stringData)$
|
|
|
|
version: 3.7.1
|
|
|
|
`,
|
|
|
|
expected: `apiVersion: v1
|
|
|
|
data:
|
|
|
|
.dockerconfigjson: eyJtYXNrIjoiKipTT1BTKioifQ==
|
|
|
|
kind: Secret
|
|
|
|
metadata:
|
|
|
|
name: secret
|
|
|
|
type: kubernetes.io/dockerconfigjson
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
r, err := yaml.Parse(tc.yamlStr)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to parse yaml: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
resource := &resource.Resource{RNode: *r}
|
|
|
|
err = maskSopsData(resource)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to trim sops data: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
sYaml, err := resource.AsYAML()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to convert sanitized resources to yaml: %v", err)
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff(string(sYaml), tc.expected); diff != "" {
|
|
|
|
t.Errorf("unexpected sanitized resources: (-got +want)%v", diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_unMarshallKustomization(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
localKsFile string
|
|
|
|
wantErr bool
|
|
|
|
errString string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "valid kustomization",
|
|
|
|
localKsFile: "testdata/local-kustomization/valid.yaml",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Multi-doc yaml containing kustomization and other resources",
|
|
|
|
localKsFile: "testdata/local-kustomization/multi-doc-valid.yaml",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no namespace",
|
|
|
|
localKsFile: "testdata/local-kustomization/no-ns.yaml",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "kustomization with a different name",
|
|
|
|
localKsFile: "testdata/local-kustomization/different-name.yaml",
|
|
|
|
wantErr: true,
|
|
|
|
errString: "failed find kustomization with name",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "yaml containing other resource with same name as kustomization",
|
|
|
|
localKsFile: "testdata/local-kustomization/invalid-resource.yaml",
|
|
|
|
wantErr: true,
|
|
|
|
errString: "failed find kustomization with name",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
b := &Builder{
|
|
|
|
name: "podinfo",
|
|
|
|
namespace: "flux-system",
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
b.kustomizationFile = tt.localKsFile
|
|
|
|
ks, err := b.unMarshallKustomization()
|
|
|
|
if !tt.wantErr {
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected err '%s'", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ks.Name != b.name && ks.Namespace != b.namespace {
|
|
|
|
t.Errorf("expected kustomization '%s/%s' to match '%s/%s'",
|
|
|
|
ks.Name, ks.Namespace, b.name, b.namespace)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected error but got nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(err.Error(), tt.errString) {
|
|
|
|
t.Errorf("expected error '%s' to contain string '%s'", err.Error(), tt.errString)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_ResolveKustomization(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
localKsFile string
|
|
|
|
liveKustomization *kustomizev1.Kustomization
|
|
|
|
dryrun bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "valid kustomization",
|
|
|
|
localKsFile: "testdata/local-kustomization/valid.yaml",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "local and live kustomization",
|
|
|
|
localKsFile: "testdata/local-kustomization/valid.yaml",
|
|
|
|
liveKustomization: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
Spec: kustomizev1.KustomizationSpec{
|
|
|
|
Interval: metav1.Duration{Duration: time.Minute * 5},
|
|
|
|
Path: "./testdata/local-kustomization/valid.yaml",
|
|
|
|
},
|
|
|
|
Status: kustomizev1.KustomizationStatus{
|
|
|
|
Conditions: []metav1.Condition{
|
|
|
|
{
|
|
|
|
Type: meta.ReadyCondition,
|
|
|
|
Status: metav1.ConditionTrue,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Inventory: &kustomizev1.ResourceInventory{
|
|
|
|
Entries: []kustomizev1.ResourceRef{
|
|
|
|
{
|
|
|
|
ID: "flux-system_podinfo_v1_service_podinfo",
|
|
|
|
Version: "v1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "local and live kustomization with dryrun",
|
|
|
|
localKsFile: "testdata/local-kustomization/valid.yaml",
|
|
|
|
liveKustomization: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
Spec: kustomizev1.KustomizationSpec{
|
|
|
|
Interval: metav1.Duration{Duration: time.Minute * 5},
|
|
|
|
Path: "./testdata/local-kustomization/valid.yaml",
|
|
|
|
},
|
|
|
|
Status: kustomizev1.KustomizationStatus{
|
|
|
|
Conditions: []metav1.Condition{
|
|
|
|
{
|
|
|
|
Type: meta.ReadyCondition,
|
|
|
|
Status: metav1.ConditionTrue,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Inventory: &kustomizev1.ResourceInventory{
|
|
|
|
Entries: []kustomizev1.ResourceRef{
|
|
|
|
{
|
|
|
|
ID: "flux-system_podinfo_v1_service_podinfo",
|
|
|
|
Version: "v1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
dryrun: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "live kustomization",
|
|
|
|
liveKustomization: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
Spec: kustomizev1.KustomizationSpec{
|
|
|
|
Interval: metav1.Duration{Duration: time.Minute * 5},
|
|
|
|
Path: "./testdata/local-kustomization/valid.yaml",
|
|
|
|
},
|
|
|
|
Status: kustomizev1.KustomizationStatus{
|
|
|
|
Conditions: []metav1.Condition{
|
|
|
|
{
|
|
|
|
Type: meta.ReadyCondition,
|
|
|
|
Status: metav1.ConditionTrue,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Inventory: &kustomizev1.ResourceInventory{
|
|
|
|
Entries: []kustomizev1.ResourceRef{
|
|
|
|
{
|
|
|
|
ID: "flux-system_podinfo_v1_service_podinfo",
|
|
|
|
Version: "v1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
b := &Builder{
|
|
|
|
name: "podinfo",
|
|
|
|
namespace: "flux-system",
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
b.kustomizationFile = tt.localKsFile
|
|
|
|
b.dryRun = tt.dryrun
|
|
|
|
ks, err := b.resolveKustomization(tt.liveKustomization)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unexpected err '%s'", err)
|
|
|
|
}
|
|
|
|
if !tt.dryrun {
|
|
|
|
if b.kustomizationFile == "" {
|
|
|
|
if cmp.Diff(ks, tt.liveKustomization) != "" {
|
|
|
|
t.Errorf("expected kustomization to match live kustomization")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if tt.liveKustomization != nil && cmp.Diff(ks.Status, tt.liveKustomization.Status) != "" {
|
|
|
|
t.Errorf("expected kustomization status to match live kustomization status")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ks.Status.Inventory != nil {
|
|
|
|
fmt.Println(ks.Status.Inventory)
|
|
|
|
t.Errorf("expected kustomization status to be nil")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_isKustomization(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
expected bool
|
|
|
|
object *unstructured.Unstructured
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "flux kustomization",
|
|
|
|
object: &unstructured.Unstructured{
|
|
|
|
Object: map[string]interface{}{
|
|
|
|
"apiVersion": "kustomize.toolkit.fluxcd.io/v1",
|
|
|
|
"kind": "Kustomization",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "other kustomization",
|
|
|
|
object: &unstructured.Unstructured{
|
|
|
|
Object: map[string]interface{}{
|
|
|
|
"apiVersion": "kustomize.config.k8s.io/v1beta1",
|
|
|
|
"kind": "Kustomization",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "wrong kind",
|
|
|
|
object: &unstructured.Unstructured{
|
|
|
|
Object: map[string]interface{}{
|
|
|
|
"apiVersion": "kustomize.toolkit.fluxcd.io/v1",
|
|
|
|
"kind": "ConfigMap",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "wrong object",
|
|
|
|
object: &unstructured.Unstructured{
|
|
|
|
Object: map[string]interface{}{
|
|
|
|
"apiVersion": "v1",
|
|
|
|
"kind": "ConfigMap",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
actual := isKustomization(tt.object)
|
|
|
|
if actual != tt.expected {
|
|
|
|
t.Fatalf("got '%v', want '%v'", actual, tt.expected)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_kustomizationsEqual(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
kustomization1 *kustomizev1.Kustomization
|
|
|
|
kustomization2 *kustomizev1.Kustomization
|
|
|
|
expected bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "equal",
|
|
|
|
kustomization1: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
kustomization2: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "wrong name",
|
|
|
|
kustomization1: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
kustomization2: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "my-app",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "wrong namespace",
|
|
|
|
kustomization1: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
kustomization2: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "my-ns",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "wrong name and namespace",
|
|
|
|
kustomization1: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "podinfo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
kustomization2: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "my-app",
|
|
|
|
Namespace: "my-ns",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
actual := kustomizationsEqual(tt.kustomization1, tt.kustomization2)
|
|
|
|
if actual != tt.expected {
|
|
|
|
t.Fatalf("got '%v', want '%v'", actual, tt.expected)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_kustomizationPath(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
kustomization *kustomizev1.Kustomization
|
|
|
|
expected string
|
|
|
|
wantErr bool
|
|
|
|
errString string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "full repo",
|
|
|
|
kustomization: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "my-app",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
Spec: kustomizev1.KustomizationSpec{
|
|
|
|
Path: "my-path",
|
|
|
|
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
|
|
|
Kind: "GitRepository",
|
|
|
|
Name: "my-repo",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: "path/to/local/git/my-path",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "repo without namespace",
|
|
|
|
kustomization: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "my-app",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
Spec: kustomizev1.KustomizationSpec{
|
|
|
|
Path: "my-path",
|
|
|
|
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
|
|
|
Kind: "GitRepository",
|
|
|
|
Name: "my-repo",
|
|
|
|
Namespace: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: "path/to/local/git/my-path",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "repo not found",
|
|
|
|
kustomization: &kustomizev1.Kustomization{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: "my-app",
|
|
|
|
Namespace: "flux-system",
|
|
|
|
},
|
|
|
|
Spec: kustomizev1.KustomizationSpec{
|
|
|
|
Path: "my-path",
|
|
|
|
SourceRef: kustomizev1.CrossNamespaceSourceReference{
|
|
|
|
Kind: "GitRepository",
|
|
|
|
Name: "my-repo",
|
|
|
|
Namespace: "my-ns",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
wantErr: true,
|
|
|
|
errString: "cannot get local path",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
b := &Builder{
|
|
|
|
name: "podinfo",
|
|
|
|
namespace: "flux-system",
|
|
|
|
localSources: map[string]string{
|
|
|
|
"GitRepository/flux-system/my-repo": "./path/to/local/git",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
actual, err := b.kustomizationPath(tt.kustomization)
|
|
|
|
if !tt.wantErr {
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected err '%s'", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if actual != tt.expected {
|
|
|
|
t.Errorf("got '%v', want '%v'", actual, tt.expected)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected error but got nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(err.Error(), tt.errString) {
|
|
|
|
t.Errorf("expected error '%s' to contain string '%s'", err.Error(), tt.errString)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|