diff --git a/.github/workflows/cache-clean-up.yaml b/.github/workflows/cache-clean-up.yaml new file mode 100644 index 0000000..e6bdb12 --- /dev/null +++ b/.github/workflows/cache-clean-up.yaml @@ -0,0 +1,29 @@ +name: cleanup caches by a branch +on: + pull_request: + types: + - closed + +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - name: Cleanup + run: | + gh extension install actions/gh-actions-cache + + echo "Fetching list of cache key" + cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 ) + + ## Setting this to not fail the workflow while deleting cache keys. + set +e + echo "Deleting caches..." + for cacheKey in $cacheKeysForPR + do + gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm + done + echo "Done" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge diff --git a/.github/workflows/ci-base.yml b/.github/workflows/ci-base.yml new file mode 100644 index 0000000..40431a5 --- /dev/null +++ b/.github/workflows/ci-base.yml @@ -0,0 +1,48 @@ +name: Check and build Kardinal Operator + +permissions: + id-token: write + contents: read + +on: + push: + branches: + - main + tags: + - "v*.*.*" + pull_request: + branches: + - main + +jobs: + check_go: + name: Check Go + runs-on: ubuntu-22.04 + steps: + - name: Git checkout + uses: actions/checkout@v3 + + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: '^1.22.0' + + - name: Check Go formatting + run: | + if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then + exit 1 + fi + + build: + name: Build + needs: [check_go] + runs-on: ubuntu-22.04 + steps: + - name: Git checkout + uses: actions/checkout@v3 + + - name: Build operator binary + run: make build + + - name: Linter + run: make lint diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml new file mode 100644 index 0000000..8e2414e --- /dev/null +++ b/.github/workflows/ci-tests.yml @@ -0,0 +1,67 @@ +name: Tests + +permissions: + id-token: write + contents: read + +on: + push: + branches: + - main + tags: + - "v*.*.*" + pull_request: + branches: + - main + +jobs: + tests: + name: Tests + runs-on: ubuntu-22.04 + steps: + - name: Git checkout + uses: actions/checkout@v3 + + - name: Start minikube + uses: manusa/actions-setup-minikube@v2.11.0 + id: minikube + with: + minikube version: "v1.33.0" + kubernetes version: "v1.30.0" + driver: docker + start args: --embed-certs --addons=ingress,metrics-server + + - name: Install Istio + run: | + ISTIO_VERSION="1.23.0" + echo "Installing Istio ..." + mkdir istio_tmp + pushd istio_tmp >/dev/null + curl -L https://istio.io/downloadIstio | ISTIO_VERSION=${ISTIO_VERSION} sh - + cd istio-${ISTIO_VERSION} + export PATH=$PWD/bin:$PATH + istioctl install --set profile=demo -y + popd + + - name: Deploy the boutique demo + run: | + kubectl create namespace baseline + kubectl apply -f ci/obd-demo.yaml -n baseline + + - name: Validate that the boutique demo is up and running + run: | + # Check that the four baseline service pods are running and ready + while [ $(kubectl get pods -n baseline --no-headers -o custom-columns=NAMESPACE:metadata.namespace,POD:metadata.name,PodIP:status.podIP,READY-true:status.containerStatuses[*].ready | grep "true" | wc -l) -ne 4 ] + do + echo "Waiting for baseline pods to run..." + kubectl get pods -n baseline -o custom-columns=NAMESPACE:metadata.namespace,POD:metadata.name,PodIP:status.podIP,READY-true:status.containerStatuses[*].ready + ((c++)) && ((c==12)) && exit 1 + sleep 10 + done + apps=$(kubectl get pods -n baseline -o custom-columns=:metadata.labels.app | tr " " "\n" | sort -g | tr "\n" " " | xargs) + echo ${apps} + if [ "${apps}" != "cartservice frontend postgres productcatalogservice" ]; then exit 1; fi + + - name: Run operator tests + run: | + make test diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml new file mode 100644 index 0000000..4173028 --- /dev/null +++ b/.github/workflows/conventional-commits.yml @@ -0,0 +1,22 @@ +# Check PR title for conventional commits +name: Check PR title +on: + pull_request_target: + types: + - opened + - reopened + - edited + - synchronize + +# cancel redundant builds +concurrency: + group: "title-checker-${{ github.head_ref }}" + cancel-in-progress: true + +jobs: + title_check: + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.golangci.yml b/.golangci.yml index aac8a13..5c03cd2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,6 +12,9 @@ issues: - path: "api/*" linters: - lll + - path: "kardinal/*" + linters: + - lll - path: "internal/*" linters: - dupl diff --git a/Makefile b/Makefile index d3fce89..cf27a38 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ vet: ## Run go vet against code. .PHONY: test test: manifests generate fmt vet envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out + USE_EXISTING_CLUSTER=true KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out # Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors. .PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up. diff --git a/ci/obd-demo.yaml b/ci/obd-demo.yaml new file mode 100644 index 0000000..e1b766d --- /dev/null +++ b/ci/obd-demo.yaml @@ -0,0 +1,334 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cartservice-v1 + labels: + app: cartservice + version: v1 +spec: + selector: + matchLabels: + app: cartservice + version: v1 + template: + metadata: + labels: + app: cartservice + version: v1 + spec: + terminationGracePeriodSeconds: 5 + containers: + - name: server + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - all + privileged: false + readOnlyRootFilesystem: true + image: kurtosistech/cartservice:main + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8090 + readinessProbe: + httpGet: + path: /health + port: 8090 + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + livenessProbe: + httpGet: + path: /health + port: 8090 + initialDelaySeconds: 15 + periodSeconds: 20 + timeoutSeconds: 5 + failureThreshold: 3 + env: + - name: PORT + value: "8090" + - name: DB_USERNAME + value: "postgresuser" + - name: DB_PASSWORD + value: "postgrespass" + - name: DB_HOST + value: "postgres" + - name: DB_PORT + value: "5432" + - name: DB_NAME + value: "cart" +--- +apiVersion: v1 +kind: Service +metadata: + name: cartservice + labels: + app: cartservice + version: v1 + annotations: + kardinal.dev.service/dependencies: "postgres:tcp" +spec: + type: ClusterIP + selector: + app: cartservice + ports: + - name: http + port: 8090 + targetPort: 8090 + protocol: TCP + appProtocol: HTTP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend-v1 + labels: + app: frontend + version: v1 +spec: + selector: + matchLabels: + app: frontend + version: v1 + template: + metadata: + labels: + app: frontend + version: v1 + annotations: + sidecar.istio.io/rewriteAppHTTPProbers: "true" + spec: + containers: + - name: server + image: kurtosistech/frontend:main + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + readinessProbe: + initialDelaySeconds: 10 + httpGet: + path: "/_healthz" + port: 8080 + httpHeaders: + - name: "Cookie" + value: "shop_session-id=x-readiness-probe" + livenessProbe: + initialDelaySeconds: 10 + httpGet: + path: "/_healthz" + port: 8080 + httpHeaders: + - name: "Cookie" + value: "shop_session-id=x-liveness-probe" + env: + - name: ADDRESS + value: ":8080" + - name: FREECURRENCYAPIKEY + value: "fca_live_nFVVF8CvfxqJhzMHB4N2x1NH7ffVVPwZr9hg3iNl" + - name: CARTSERVICEHOST + value: cartservice + - name: PRODUCTCATALOGSERVICEHOST + value: productcatalogservice + +--- +apiVersion: v1 +kind: Service +metadata: + name: frontend + labels: + app: frontend + version: v1 + annotations: + kardinal.dev.service/dependencies: "productcatalogservice:http,cartservice:http" + kardinal.dev.service/plugins: | + - name: https://github.com/kurtosis-tech/free-currency-api-plugin.git + type: external + servicename: free-currency-api + args: + api_key: fca_live_VKZlykCWEiFcpBHnw74pzd4vLi04q1h9JySbVHDF +spec: + type: ClusterIP + selector: + app: frontend + ports: + - name: http + port: 80 + protocol: TCP + appProtocol: HTTP + targetPort: 8080 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres-v1 + labels: + app: postgres + version: v1 +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + version: v1 + template: + metadata: + labels: + app: postgres + version: v1 + spec: + containers: + - name: postgres + image: "postgres:14" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: "cart" + - name: POSTGRES_USER + value: "postgresuser" + - name: POSTGRES_PASSWORD + value: "postgrespass" + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgres-data + volumes: + - name: postgres-data + emptyDir: {} + +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + labels: + app: postgres + version: v1 + annotations: + kardinal.dev.service/stateful: "true" + kardinal.dev.service/plugins: | + - name: github.com/kurtosis-tech/postgres-seed-plugin + args: + seed_script: | + -- create the table + CREATE TABLE IF NOT EXISTS public.items( + id bigserial PRIMARY KEY, + created_at TIMESTAMP WITH TIME ZONE, + updated_at TIMESTAMP WITH TIME ZONE, + deleted_at TIMESTAMP WITH TIME ZONE, + user_id TEXT, + product_id TEXT, + quantity INTEGER + ); + + INSERT INTO public.items (id, created_at, updated_at, deleted_at, user_id, product_id, quantity) + VALUES (1, '2024-08-02 13:02:07.656104 +00:00', '2024-08-02 13:02:07.656104 +00:00', null, '0494c5e0-dde0-48fa-a6d8-f7962f5476bf', '66VCHSJNUP', 1); + + INSERT INTO public.items (id, created_at, updated_at, deleted_at, user_id, product_id, quantity) + VALUES (2, '2024-08-02 13:02:10.891407 +00:00', '2024-08-02 13:02:10.891407 +00:00', null, '0494c5e0-dde0-48fa-a6d8-f7962f5476bf', '2ZYFJ3GM2N', 1); + + -- Set the sequence to the correct value after inserting records + SELECT setval('public.items_id_seq', (SELECT MAX(id) FROM public.items)); + db_name: "cart" + db_user: "postgresuser" + db_password: "postgrespass" + +spec: + type: ClusterIP + ports: + - name: tcp + port: 5432 + targetPort: 5432 + protocol: TCP + selector: + app: postgres + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: productcatalogservice-v1 + labels: + app: productcatalogservice + version: v1 +spec: + selector: + matchLabels: + app: productcatalogservice + version: v1 + template: + metadata: + labels: + app: productcatalogservice + version: v1 + spec: + terminationGracePeriodSeconds: 5 + containers: + - name: server + image: kurtosistech/productcatalogservice:main + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8070 + readinessProbe: + httpGet: + path: /health + port: 8070 + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + livenessProbe: + httpGet: + path: /health + port: 8070 + initialDelaySeconds: 15 + periodSeconds: 20 + timeoutSeconds: 5 + failureThreshold: 3 + env: + - name: PORT + value: "8070" +--- +apiVersion: v1 +kind: Service +metadata: + name: productcatalogservice + labels: + app: productcatalogservice + version: v1 +spec: + type: ClusterIP + selector: + app: productcatalogservice + ports: + - name: http + port: 8070 + targetPort: 8070 + protocol: TCP + appProtocol: HTTP + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: nginx + kardinal.dev.service/ingress: "true" + name: ingress +spec: + rules: + - host: prod.app.localhost + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: frontend + port: + number: 80 diff --git a/go.mod b/go.mod index dbf4869..83185ed 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,12 @@ module kardinal.dev/kardinal-operator go 1.22.0 require ( + github.com/brunoga/deep v1.2.4 + github.com/kurtosis-tech/stacktrace v0.0.0-20211028211901-1c67a77b5409 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 + github.com/samber/lo v1.47.0 + github.com/sirupsen/logrus v1.9.3 k8s.io/api v0.31.0 k8s.io/apimachinery v0.31.0 k8s.io/client-go v0.31.0 @@ -19,7 +23,6 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dominikbraun/graph v0.23.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -46,7 +49,6 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kurtosis-tech/stacktrace v0.0.0-20211028211901-1c67a77b5409 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -56,8 +58,6 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/samber/lo v1.47.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect diff --git a/go.sum b/go.sum index 170b5ff..6dd474d 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/brunoga/deep v1.2.4 h1:Aj9E9oUbE+ccbyh35VC/NHlzzjfIVU69BXu2mt2LmL8= +github.com/brunoga/deep v1.2.4/go.mod h1:GDV6dnXqn80ezsLSZ5Wlv1PdKAWAO4L5PnKYtv2dgaI= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -16,8 +18,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= -github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k= diff --git a/internal/controller/core/flow_controller_test.go b/internal/controller/core/flow_controller_test.go index e6eda65..0ddfbc1 100644 --- a/internal/controller/core/flow_controller_test.go +++ b/internal/controller/core/flow_controller_test.go @@ -38,7 +38,7 @@ var _ = Describe("Flow Controller", func() { typeNamespacedName := types.NamespacedName{ Name: resourceName, - Namespace: "default", // TODO(user):Modify as needed + Namespace: "baseline", } flow := &corev1.Flow{} @@ -49,9 +49,12 @@ var _ = Describe("Flow Controller", func() { resource := &corev1.Flow{ ObjectMeta: metav1.ObjectMeta{ Name: resourceName, - Namespace: "default", + Namespace: "baseline", + }, + Spec: corev1.FlowSpec{ + Service: "frontend", + Image: "kurtosistech/frontend:demo-frontend", }, - // TODO(user): Specify other spec details if needed. } Expect(k8sClient.Create(ctx, resource)).To(Succeed()) } diff --git a/kardinal/topology/topology.go b/kardinal/topology/topology.go index bc4c3ad..639e7fa 100644 --- a/kardinal/topology/topology.go +++ b/kardinal/topology/topology.go @@ -7,6 +7,7 @@ import ( "fmt" "strings" + "github.com/brunoga/deep" "github.com/kurtosis-tech/stacktrace" "github.com/samber/lo" "github.com/sirupsen/logrus" @@ -19,6 +20,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) +const ( + trueStr = "true" +) + type ClusterTopology struct { FlowID string `json:"flowID"` Ingress *Ingress `json:"ingress"` @@ -44,7 +49,10 @@ func (clusterTopology *ClusterTopology) UpdateWithFlow(flowPatch *FlowPatch) err if err != nil { return stacktrace.Propagate(err, "An error occurred retrieving the service %s in namespace %s", servicePatch.Service, servicePatch.Namespace) } - modifiedTargetService := DeepCopyService(targetService) + modifiedTargetService, err := deep.Copy(targetService) + if err != nil { + return stacktrace.Propagate(err, "An error occurred copying the target service %s", targetService.ServiceID) + } modifiedTargetService.DeploymentSpec = servicePatch.DeploymentSpec modifiedTargetService.Version = flowID modifiedTargetService.IsManaged = true @@ -104,7 +112,7 @@ func (clusterTopology *ClusterTopology) ApplyResources(ctx context.Context, clus for _, service := range namespace.Services { serviceAnnotations := service.Annotations isManaged, found := serviceAnnotations["kardinal.dev/managed"] - if found && isManaged == "true" { + if found && isManaged == trueStr { if clusterTopologyNamespace == nil || clusterTopologyNamespace.GetService(service.Name) == nil { logrus.Infof("Deleting service %s", service.Name) _ = cl.Delete(ctx, service) @@ -114,7 +122,7 @@ func (clusterTopology *ClusterTopology) ApplyResources(ctx context.Context, clus for _, deployment := range namespace.Deployments { deploymentAnnotations := deployment.Annotations isManaged, found := deploymentAnnotations["kardinal.dev/managed"] - if found && isManaged == "true" { + if found && isManaged == trueStr { if clusterTopologyNamespace == nil || clusterTopologyNamespace.GetDeployment(deployment.Name) == nil { logrus.Infof("Deleting deployment %s", deployment.Name) _ = cl.Delete(ctx, deployment) @@ -142,7 +150,7 @@ type Service struct { func (service *Service) GetCoreV1Service(namespace string) *corev1.Service { kardinalManaged := "false" if service.Version != namespace { - kardinalManaged = "true" + kardinalManaged = trueStr } return &corev1.Service{ TypeMeta: metav1.TypeMeta{ @@ -166,7 +174,7 @@ func (service *Service) GetCoreV1Service(namespace string) *corev1.Service { func (service *Service) GetAppsV1Deployment(namespace string) *appsv1.Deployment { kardinalManaged := "false" if service.Version != namespace { - kardinalManaged = "true" + kardinalManaged = trueStr } deployment := appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ @@ -205,7 +213,7 @@ func (service *Service) GetAppsV1Deployment(namespace string) *appsv1.Deployment } deployment.Spec.Template.ObjectMeta = metav1.ObjectMeta{ Annotations: map[string]string{ - "sidecar.istio.io/inject": "true", + "sidecar.istio.io/inject": trueStr, // TODO: make this a flag to help debugging // One can view the logs with: kubeclt logs -f -l app= -n -c istio-proxy "sidecar.istio.io/componentLogLevel": "lua:info", @@ -233,19 +241,19 @@ func NewServiceFromServiceAndDeployment(coreV1Service *corev1.Service, deploymen clusterTopologyService.DeploymentSpec = &deployment.Spec } isStateful, ok := serviceAnnotations["kardinal.dev.service/stateful"] - if ok && isStateful == "true" { + if ok && isStateful == trueStr { clusterTopologyService.IsStateful = true } isExternal, ok := serviceAnnotations["kardinal.dev.service/external"] - if ok && isExternal == "true" { + if ok && isExternal == trueStr { clusterTopologyService.IsExternal = true } isShared, ok := serviceAnnotations["kardinal.dev.service/shared"] - if ok && isShared == "true" { + if ok && isShared == trueStr { clusterTopologyService.IsShared = true } isManaged, ok := serviceAnnotations["kardinal.dev/managed"] - if ok && isManaged == "true" { + if ok && isManaged == trueStr { clusterTopologyService.IsManaged = true } return clusterTopologyService diff --git a/kardinal/topology/utils.go b/kardinal/topology/utils.go index 74e6acf..5652d81 100644 --- a/kardinal/topology/utils.go +++ b/kardinal/topology/utils.go @@ -1,62 +1,6 @@ package topology -import ( - "encoding/json" - - appsv1 "k8s.io/api/apps/v1" -) - -// Hack the to deep copy the topology. oh go! :( -// Plase, avoid using this function directly. Instead implement a direct and specific wrapper function -// DeepCopyDeploymentSpec or DeepCopyService. If you use it, make sure to the dst argument as a pointer -// and test it properly. -func unsafeDeepCopy(src, dst interface{}) { - bytes, err := json.Marshal(src) - if err != nil { - panic(err) - } - json.Unmarshal(bytes, dst) -} - -func deepCopySlice[T any](orig []T) []T { - cpy := make([]T, len(orig)) - copy(cpy, orig) - return cpy -} - // Helper function to create int32 pointers func int32Ptr(i int32) *int32 { return &i } - -func DeepCopyDeploymentSpec(src *appsv1.DeploymentSpec) *appsv1.DeploymentSpec { - dst := &appsv1.DeploymentSpec{} - unsafeDeepCopy(src, dst) - return dst -} - -func DeepCopyService(src *Service) *Service { - dst := &Service{} - unsafeDeepCopy(src, dst) - return dst -} - -func DeepCopyClusterTopology(src *ClusterTopology) *ClusterTopology { - dst := &ClusterTopology{} - unsafeDeepCopy(src, dst) - return dst -} - -func DeepCopyIngress(src *Ingress) *Ingress { - dst := &Ingress{} - unsafeDeepCopy(src, dst) - return dst -} - -func SPrintJSONClusterTopology(clusterTopology *ClusterTopology) string { - bytes, err := json.MarshalIndent(clusterTopology, "", " ") - if err != nil { - panic("Error marshalling cluster topology") - } - return string(bytes) -}