diff --git a/clabverter/assets/topology.yaml.template b/clabverter/assets/topology.yaml.template index d7194fd9..31685390 100644 --- a/clabverter/assets/topology.yaml.template +++ b/clabverter/assets/topology.yaml.template @@ -1,5 +1,5 @@ --- -apiVersion: topologies.containerlab.dev/v1alpha1 +apiVersion: clabernetes.containerlab.dev/v1alpha1 kind: Topology metadata: name: {{ .Name }} diff --git a/clabverter/test-fixtures/golden/srl02.yaml b/clabverter/test-fixtures/golden/srl02.yaml index 4acf0c66..ba3eabb5 100755 --- a/clabverter/test-fixtures/golden/srl02.yaml +++ b/clabverter/test-fixtures/golden/srl02.yaml @@ -1,4 +1,4 @@ -apiVersion: topologies.containerlab.dev/v1alpha1 +apiVersion: clabernetes.containerlab.dev/v1alpha1 kind: Topology metadata: creationTimestamp: null diff --git a/config/bootstrap.go b/config/bootstrap.go index 371c0dad..5dd28431 100644 --- a/config/bootstrap.go +++ b/config/bootstrap.go @@ -105,7 +105,13 @@ func bootstrapFromConfigMap( //nolint:gocyclo,funlen } launcherImage, launcherImageOk := inMap["launcherImage"] - if launcherImageOk { + if launcherImageOk && launcherImage != "" { + // check for empty string too -- the config map by default (w/ default values) will always + // have just "" for launcher image, config bootstrapping will use the value set in the + // LAUNCHER_IMAGE env which will be the same kind of resolution we have for manager image + // where user provided value takes precedent, then if unset and "0.0.0" chart version it + // results in dev-latest image tag, finally, resulting in just the image w/ the tag the same + // as the chart version. bc.launcherImage = launcherImage } diff --git a/config/manager.go b/config/manager.go index 12b56f8d..95096e9c 100644 --- a/config/manager.go +++ b/config/manager.go @@ -211,7 +211,7 @@ func (m *manager) Start() error { found = false } else { - m.logger.Criticalf("encountered error fetching global config, err: ", err) + m.logger.Criticalf("encountered error fetching global config, err: %s", err) return err } diff --git a/constants/env.go b/constants/env.go index 1866568d..d607151c 100644 --- a/constants/env.go +++ b/constants/env.go @@ -53,10 +53,6 @@ const ( // (launcher) pods. LauncherImageEnv = "LAUNCHER_IMAGE" - // LauncherPullPolicyEnv env var that tells the controllers what pull policy to use for - // clabernetes (launcher) pods. - LauncherPullPolicyEnv = "LAUNCHER_PULL_POLICY" - // LauncherPrivilegedEnv is an envar that indicates if the launcher is launched with // privileged mode or our "not so privileged mode". LauncherPrivilegedEnv = "LAUNCHER_PRIVILEGED" diff --git a/e2e/clabverter/clabverter_basic_test.go b/e2e/clabverter/clabverter_basic_test.go new file mode 100644 index 00000000..469df655 --- /dev/null +++ b/e2e/clabverter/clabverter_basic_test.go @@ -0,0 +1,80 @@ +package clabverter_test + +import ( + "fmt" + "os" + "testing" + + clabernetesclabverter "github.com/srl-labs/clabernetes/clabverter" + clabernetestesthelper "github.com/srl-labs/clabernetes/testhelper" + clabernetestesthelpersuite "github.com/srl-labs/clabernetes/testhelper/suite" +) + +func TestMain(m *testing.M) { + clabernetestesthelper.Flags() + + os.Exit(m.Run()) +} + +func TestClabverterBasic(t *testing.T) { + t.Parallel() + + testName := "clabverter-basic" + + namespace := clabernetestesthelper.NewTestNamespace(testName) + + c := clabernetesclabverter.MustNewClabverter( + "test-fixtures/basic_clab.yaml", + "test-fixtures", + namespace, + "", + false, + false, + false, + ) + + err := c.Clabvert() + if err != nil { + t.Fatalf("failed running clabversion, err: %s", err) + } + + // rename the generated topo so we can use the e2e runner thingy + err = os.Rename("test-fixtures/clabverter-basic.yaml", "test-fixtures/10-apply.yaml") + if err != nil { + t.Fatalf("failed renaming clabverted topology, err: %s", err) + } + + defer func() { + err = os.Remove("test-fixtures/10-apply.yaml") + if err != nil { + t.Errorf("failed cleaning up clabverted topology file, err: %s", err) + } + }() + + steps := clabernetestesthelpersuite.Steps{ + { + Index: 10, + Description: "Create a simple containerlab topology from clabverted output", + AssertObjects: map[string][]clabernetestesthelpersuite.AssertObject{ + "topology": { + { + Name: testName, + NormalizeFuncs: []func(t *testing.T, objectData []byte) []byte{ + clabernetestesthelper.NormalizeTopology, + }, + }, + }, + "service": { + { + Name: fmt.Sprintf("%s-srl1", testName), + NormalizeFuncs: []func(t *testing.T, objectData []byte) []byte{ + clabernetestesthelper.NormalizeExposeService, + }, + }, + }, + }, + }, + } + + clabernetestesthelpersuite.Run(t, steps, namespace) +} diff --git a/e2e/clabverter/test-fixtures/basic_clab.yaml b/e2e/clabverter/test-fixtures/basic_clab.yaml new file mode 100644 index 00000000..858eaa0a --- /dev/null +++ b/e2e/clabverter/test-fixtures/basic_clab.yaml @@ -0,0 +1,14 @@ +--- +name: clabverter-basic + +topology: + nodes: + srl1: + kind: srl + image: ghcr.io/nokia/srlinux + srl2: + kind: srl + image: ghcr.io/nokia/srlinux + + links: + - endpoints: ["srl1:e1-1", "srl2:e1-1"] \ No newline at end of file diff --git a/e2e/clabverter/test-fixtures/golden/10-service.clabverter-basic-srl1.yaml b/e2e/clabverter/test-fixtures/golden/10-service.clabverter-basic-srl1.yaml new file mode 100755 index 00000000..ee7e8334 --- /dev/null +++ b/e2e/clabverter/test-fixtures/golden/10-service.clabverter-basic-srl1.yaml @@ -0,0 +1,89 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + clabernetes/app: clabernetes + clabernetes/name: clabverter-basic-srl1 + clabernetes/topologyKind: containerlab + clabernetes/topologyNode: srl1 + clabernetes/topologyOwner: clabverter-basic + clabernetes/topologyServiceType: expose + name: clabverter-basic-srl1 + namespace: NAMESPACE + ownerReferences: + - apiVersion: clabernetes.containerlab.dev/v1alpha1 + kind: Topology + name: clabverter-basic +spec: + allocateLoadBalancerNodePorts: true + externalTrafficPolicy: Cluster + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: port-161-udp + port: 161 + protocol: UDP + targetPort: 60000 + - name: port-21-tcp + port: 21 + protocol: TCP + targetPort: 60000 + - name: port-22-tcp + port: 22 + protocol: TCP + targetPort: 60001 + - name: port-23-tcp + port: 23 + protocol: TCP + targetPort: 60002 + - name: port-80-tcp + port: 80 + protocol: TCP + targetPort: 60003 + - name: port-443-tcp + port: 443 + protocol: TCP + targetPort: 60004 + - name: port-830-tcp + port: 830 + protocol: TCP + targetPort: 60005 + - name: port-5000-tcp + port: 5000 + protocol: TCP + targetPort: 60006 + - name: port-5900-tcp + port: 5900 + protocol: TCP + targetPort: 60007 + - name: port-6030-tcp + port: 6030 + protocol: TCP + targetPort: 60008 + - name: port-9339-tcp + port: 9339 + protocol: TCP + targetPort: 60009 + - name: port-9340-tcp + port: 9340 + protocol: TCP + targetPort: 60010 + - name: port-9559-tcp + port: 9559 + protocol: TCP + targetPort: 60011 + - name: port-57400-tcp + port: 57400 + protocol: TCP + targetPort: 60012 + selector: + clabernetes/app: clabernetes + clabernetes/name: clabverter-basic-srl1 + clabernetes/topologyNode: srl1 + clabernetes/topologyOwner: clabverter-basic + sessionAffinity: None + type: LoadBalancer +status: + loadBalancer: {} diff --git a/e2e/clabverter/test-fixtures/golden/10-topology.clabverter-basic.yaml b/e2e/clabverter/test-fixtures/golden/10-topology.clabverter-basic.yaml new file mode 100755 index 00000000..619c9a7b --- /dev/null +++ b/e2e/clabverter/test-fixtures/golden/10-topology.clabverter-basic.yaml @@ -0,0 +1,134 @@ +apiVersion: clabernetes.containerlab.dev/v1alpha1 +kind: Topology +metadata: + annotations: {} + name: clabverter-basic + namespace: NAMESPACE +spec: + definition: + containerlab: |- + --- + name: clabverter-basic + + topology: + nodes: + srl1: + kind: srl + image: ghcr.io/nokia/srlinux + srl2: + kind: srl + image: ghcr.io/nokia/srlinux + + links: + - endpoints: ["srl1:e1-1", "srl2:e1-1"] + deployment: + persistence: + enabled: false + expose: + disableAutoExpose: false + disableExpose: false + disableNodeAliasService: false + imagePull: {} +status: + configs: + srl1: | + name: clabernetes-srl1 + prefix: "" + topology: + defaults: + ports: + - 60000:21/tcp + - 60001:22/tcp + - 60002:23/tcp + - 60003:80/tcp + - 60000:161/udp + - 60004:443/tcp + - 60005:830/tcp + - 60006:5000/tcp + - 60007:5900/tcp + - 60008:6030/tcp + - 60009:9339/tcp + - 60010:9340/tcp + - 60011:9559/tcp + - 60012:57400/tcp + nodes: + srl1: + kind: srl + image: ghcr.io/nokia/srlinux + ports: [] + links: + - endpoints: + - srl1:e1-1 + - host:srl1-e1-1 + debug: false + srl2: | + name: clabernetes-srl2 + prefix: "" + topology: + defaults: + ports: + - 60000:21/tcp + - 60001:22/tcp + - 60002:23/tcp + - 60003:80/tcp + - 60000:161/udp + - 60004:443/tcp + - 60005:830/tcp + - 60006:5000/tcp + - 60007:5900/tcp + - 60008:6030/tcp + - 60009:9339/tcp + - 60010:9340/tcp + - 60011:9559/tcp + - 60012:57400/tcp + nodes: + srl2: + kind: srl + image: ghcr.io/nokia/srlinux + ports: [] + links: + - endpoints: + - srl2:e1-1 + - host:srl2-e1-1 + debug: false + exposedPorts: + srl1: + tcpPorts: + - 21 + - 22 + - 23 + - 80 + - 443 + - 830 + - 5000 + - 5900 + - 6030 + - 9339 + - 9340 + - 9559 + - 57400 + udpPorts: + - 161 + srl2: + tcpPorts: + - 21 + - 22 + - 23 + - 80 + - 443 + - 830 + - 5000 + - 5900 + - 6030 + - 9339 + - 9340 + - 9559 + - 57400 + udpPorts: + - 161 + kind: containerlab + reconcileHashes: + config: 25ea403243c3741d3013049756aa02db0ad8dc3d0d9bf803dc1576f9dda33649 + filesFromURL: {} + imagePullSecrets: 37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570 + tunnels: 25ea403243c3741d3013049756aa02db0ad8dc3d0d9bf803dc1576f9dda33649 diff --git a/e2e/topology/basic/topology_basic_test.go b/e2e/topology/basic/topology_basic_test.go index 06922dfe..5fe9b358 100644 --- a/e2e/topology/basic/topology_basic_test.go +++ b/e2e/topology/basic/topology_basic_test.go @@ -16,50 +16,13 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } -func normalizeContainerlab(t *testing.T, objectData []byte) []byte { - t.Helper() - - // unfortunately we need to remove the hash bits since any cluster may have no lb or get a - // different lb address assigned than what we have stored in golden file(s) - objectData = clabernetestesthelper.YQCommand( - t, - objectData, - "del(.status.reconcileHashes.exposedPorts)", - ) - objectData = clabernetestesthelper.YQCommand( - t, - objectData, - "del(.status.exposedPorts[].loadBalancerAddress)", - ) - - return objectData -} - -func normalizeExposeService(t *testing.T, objectData []byte) []byte { - t.Helper() - - // cluster ips obviously are going to be different all the time so we'll ignore them - objectData = clabernetestesthelper.YQCommand(t, objectData, "del(.spec.clusterIP)") - objectData = clabernetestesthelper.YQCommand(t, objectData, "del(.spec.clusterIPs)") - - // remove node ports since they'll be random - objectData = clabernetestesthelper.YQCommand(t, objectData, "del(.spec.ports[].nodePort)") - - // and the lb ip in status because of course that may be different depending on cluster - objectData = clabernetestesthelper.YQCommand( - t, - objectData, - ".status.loadBalancer = {}", - ) - - return objectData -} - func TestContainerlabBasic(t *testing.T) { t.Parallel() testName := "topology-basic" + namespace := clabernetestesthelper.NewTestNamespace(testName) + steps := clabernetestesthelpersuite.Steps{ { // this step, while obviously very "basic" does quite a bit of work for us... it ensures @@ -73,7 +36,7 @@ func TestContainerlabBasic(t *testing.T) { { Name: testName, NormalizeFuncs: []func(t *testing.T, objectData []byte) []byte{ - normalizeContainerlab, + clabernetestesthelper.NormalizeTopology, }, }, }, @@ -81,7 +44,7 @@ func TestContainerlabBasic(t *testing.T) { { Name: fmt.Sprintf("%s-srl1", testName), NormalizeFuncs: []func(t *testing.T, objectData []byte) []byte{ - normalizeExposeService, + clabernetestesthelper.NormalizeExposeService, }, }, }, @@ -89,5 +52,5 @@ func TestContainerlabBasic(t *testing.T) { }, } - clabernetestesthelpersuite.Run(t, steps, testName) + clabernetestesthelpersuite.Run(t, steps, namespace) } diff --git a/testhelper/kubernetes.go b/testhelper/kubernetes.go index 4ca307b5..fc4cf6cc 100644 --- a/testhelper/kubernetes.go +++ b/testhelper/kubernetes.go @@ -3,15 +3,23 @@ package testhelper import ( "testing" - clabernetesutilkubernetes "github.com/srl-labs/clabernetes/util/kubernetes" - clabernetesutil "github.com/srl-labs/clabernetes/util" + clabernetesutilkubernetes "github.com/srl-labs/clabernetes/util/kubernetes" ) const ( namespaceRandomPad = 8 ) +// NewTestNamespace generates a namespace for a test. +func NewTestNamespace(testName string) string { + return clabernetesutilkubernetes.SafeConcatNameKubernetes( + "e2e", + testName, + clabernetesutil.RandomString(namespaceRandomPad), + ) +} + // NormalizeKubernetesObject does some janky regex replace to remove controller generated fields // we don't want to compare. func NormalizeKubernetesObject(t *testing.T, object []byte) []byte { @@ -48,11 +56,45 @@ func NormalizeKubernetesObject(t *testing.T, object []byte) []byte { return object } -// NewTestNamespace generates a namespace for a test. -func NewTestNamespace(testName string) string { - return clabernetesutilkubernetes.SafeConcatNameKubernetes( - "e2e", - testName, - clabernetesutil.RandomString(namespaceRandomPad), +// NormalizeTopology normalizes a clabernetes topology cr by removing fields that may change between +// ci and local or other folks machines/clusters -- so we can compare results more easily. +func NormalizeTopology(t *testing.T, objectData []byte) []byte { + t.Helper() + + // unfortunately we need to remove the hash bits since any cluster may have no lb or get a + // different lb address assigned than what we have stored in golden file(s) + objectData = YQCommand( + t, + objectData, + "del(.status.reconcileHashes.exposedPorts)", + ) + objectData = YQCommand( + t, + objectData, + "del(.status.exposedPorts[].loadBalancerAddress)", + ) + + return objectData +} + +// NormalizeExposeService normalizes a service cr by removing fields that may change between ci and +// local or other folks machines/clusters -- so we can compare results more easily. +func NormalizeExposeService(t *testing.T, objectData []byte) []byte { + t.Helper() + + // cluster ips obviously are going to be different all the time so we'll ignore them + objectData = YQCommand(t, objectData, "del(.spec.clusterIP)") + objectData = YQCommand(t, objectData, "del(.spec.clusterIPs)") + + // remove node ports since they'll be random + objectData = YQCommand(t, objectData, "del(.spec.ports[].nodePort)") + + // and the lb ip in status because of course that may be different depending on cluster + objectData = YQCommand( + t, + objectData, + ".status.loadBalancer = {}", ) + + return objectData } diff --git a/testhelper/suite/run.go b/testhelper/suite/run.go index 3e2d98b2..76dab64b 100644 --- a/testhelper/suite/run.go +++ b/testhelper/suite/run.go @@ -15,9 +15,7 @@ const ( ) // Run executes a clabernetes e2e test. -func Run(t *testing.T, steps []Step, testName string) { //nolint: thelper - namespace := clabernetestesthelper.NewTestNamespace(testName) - +func Run(t *testing.T, steps []Step, namespace string) { //nolint: thelper clabernetestesthelper.KubectlCreateNamespace(t, namespace) defer func() {