From 83e6dc2a83feb489ebb5dc266857ba6e0d06c71b Mon Sep 17 00:00:00 2001 From: leoporoli Date: Wed, 28 Aug 2024 09:36:55 -0300 Subject: [PATCH] feat: print cluster topology manifest CLI cmd (#172) --- kardinal-cli/cmd/root.go | 77 ++++++++++++++++++++++++++- kardinal-cli/deployment/deployment.go | 69 ++++++++++++++++++------ 2 files changed, 128 insertions(+), 18 deletions(-) diff --git a/kardinal-cli/cmd/root.go b/kardinal-cli/cmd/root.go index 993f079c..c62d1d5b 100644 --- a/kardinal-cli/cmd/root.go +++ b/kardinal-cli/cmd/root.go @@ -3,6 +3,7 @@ package cmd import ( "context" "fmt" + "io" "log" "os" "path" @@ -30,8 +31,9 @@ import ( ) const ( - kontrolBaseURLTmpl = "%s://%s" - kontrolClusterResourcesEndpointTmpl = "%s/tenant/%s/cluster-resources" + kontrolBaseURLTmpl = "%s://%s" + kontrolClusterResourcesEndpointTmpl = "%s/tenant/%s/cluster-resources" + kontrolClusterResourcesManifestEndpointTmpl = "%s/tenant/%s/cluster-resources/manifest" kontrolTrafficConfigurationURLTmpl = "%s/%s/traffic-configuration" @@ -43,6 +45,9 @@ const ( httpSchme = "http" httpsScheme = httpSchme + "s" + + addTraceRouterFlagName = "add-trace-router" + yamlSeparator = "---" ) var ( @@ -75,6 +80,11 @@ var templateCmd = &cobra.Command{ Short: "Manage template creation", } +var topologyCmd = &cobra.Command{ + Use: "topology", + Short: "Manage Kardinal topologies", +} + var tenantCmd = &cobra.Command{ Use: "tenant", Short: "Manage tenant", @@ -219,6 +229,55 @@ var deleteCmd = &cobra.Command{ }, } +var topologyManifestCmd = &cobra.Command{ + Use: "print-manifest", + Short: "print the current cluster topology manifest deployed in Kontrol", + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + addTraceRouter, err := cmd.Flags().GetBool(addTraceRouterFlagName) + if err != nil { + log.Fatalf("Error getting add-trace-router flag: %v", err) + } + + tenantUuid, err := tenant.GetOrCreateUserTenantUUID() + if err != nil { + log.Fatal("Error getting or creating user tenant UUID", err) + } + + ctx := context.Background() + client := getKontrolServiceClient() + + resp, err := client.GetTenantUuidManifest(ctx, tenantUuid.String()) + if err != nil { + log.Fatalf("Failed to get topology manifest: %v", err) + } + + if resp == nil || resp.StatusCode != 200 { + log.Fatalf("Not Topology manifest successfull response, response status code: %d", resp.StatusCode) + } + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + log.Fatalf("Error reading response body: %v\n", err) + return + } + + topologyManifest := string(bodyBytes) + + manifestToPrint := topologyManifest + + if addTraceRouter { + traceRouterManifest, err := deployment.GetKardinalTraceRouterManifest() + if err != nil { + log.Fatalf("Error getting kardinal-trace router manifest: %v", err) + } + manifestToPrint = manifestToPrint + yamlSeparator + traceRouterManifest + } + + fmt.Println(manifestToPrint) + }, +} + var deployManagerCmd = &cobra.Command{ Use: fmt.Sprintf("deploy [kontrol location] accepted values: %s and %s ", kontrol.KontrolLocationLocalMinikube, kontrol.KontrolLocationKloudKontrol), Short: "Deploy Kardinal manager into the cluster", @@ -373,10 +432,13 @@ func init() { rootCmd.AddCommand(dashboardCmd) rootCmd.AddCommand(gatewayCmd) rootCmd.AddCommand(reportInstall) + rootCmd.AddCommand(topologyCmd) rootCmd.AddCommand(tenantCmd) flowCmd.AddCommand(listCmd, createCmd, deleteCmd) managerCmd.AddCommand(deployManagerCmd, removeManagerCmd) templateCmd.AddCommand(templateCreateCmd, templateDeleteCmd, templateListCmd) + topologyCmd.AddCommand(topologyManifestCmd) + topologyManifestCmd.Flags().BoolP(addTraceRouterFlagName, "", false, "Include the trace router in the printed manifest") tenantCmd.AddCommand(tenantShowCmd) createCmd.Flags().StringSliceVarP(&serviceImagePairs, "service-image", "s", []string{}, "Extra service and respective image to include in the same flow (can be used multiple times)") @@ -849,3 +911,14 @@ func getClusterResourcesURL(tenantUuid api_types.Uuid) (string, error) { return clusterResourcesURL, nil } + +func getClusterResourcesManifestURL(tenantUuid api_types.Uuid) (string, error) { + kontrolBaseURL, err := getKontrolBaseURLForManager() + if err != nil { + return "", stacktrace.Propagate(err, "An error occurred getting the Kontrol base URL") + } + + clusterResourcesURL := fmt.Sprintf(kontrolClusterResourcesManifestEndpointTmpl, kontrolBaseURL, tenantUuid) + + return clusterResourcesURL, nil +} diff --git a/kardinal-cli/deployment/deployment.go b/kardinal-cli/deployment/deployment.go index 879ce319..64da2e94 100644 --- a/kardinal-cli/deployment/deployment.go +++ b/kardinal-cli/deployment/deployment.go @@ -11,10 +11,11 @@ import ( ) const ( - kardinalNamespace = "default" - kardinalManagerDeploymentTmplName = "kardinal-manager-deployment" + kardinalNamespace = "default" + kardinalManagerDeploymentTmplName = "kardinal-manager-deployment" + kardinalTraceRouterManifestTmplName = "kardinal-trace-router-manifest" - kardinalManagerDeploymentTmpl = ` + kardinalManagerAuthTmpl = ` apiVersion: v1 kind: ServiceAccount metadata: @@ -50,8 +51,10 @@ roleRef: kind: ClusterRole name: kardinal-manager-role apiGroup: rbac.authorization.k8s.io - --- +` + + kardinalManagerDeploymentTmpl = ` apiVersion: apps/v1 kind: Deployment metadata: @@ -84,6 +87,9 @@ spec: - name: KARDINAL_MANAGER_FETCHER_JOB_DURATION_SECONDS value: "10" --- +` + + kardinalTraceRouterDeploymentTmpl = ` apiVersion: v1 kind: Service metadata: @@ -120,7 +126,7 @@ spec: containers: - name: trace-router image: kurtosistech/kardinal-router:latest - imagePullPolicy: {{.KardinalManagerContainerImagePullPolicy}} + imagePullPolicy: {{.KardinalTraceRouterContainerImagePullPolicy}} ports: - containerPort: 8080 env: @@ -170,15 +176,21 @@ spec: env: - name: ALLOW_EMPTY_PASSWORD value: "yes" +--- ` + + kardinalTraceRouterManifestTmpl = kardinalManagerAuthTmpl + kardinalTraceRouterDeploymentTmpl + + allKardinalTmpls = kardinalManagerAuthTmpl + kardinalManagerDeploymentTmpl + kardinalTraceRouterDeploymentTmpl ) type templateData struct { - Namespace string - ClusterResourcesURL string - KardinalAppIDLabelKey string - KardinalManagerAppIDLabelValue string - KardinalManagerContainerImagePullPolicy string + Namespace string + ClusterResourcesURL string + KardinalAppIDLabelKey string + KardinalManagerAppIDLabelValue string + KardinalManagerContainerImagePullPolicy string + KardinalTraceRouterContainerImagePullPolicy string } func DeployKardinalManagerInCluster(ctx context.Context, clusterResourcesURL string, kontrolLocation string) error { @@ -187,7 +199,7 @@ func DeployKardinalManagerInCluster(ctx context.Context, clusterResourcesURL str return stacktrace.Propagate(err, "An error occurred while creating the Kubernetes client") } - kardinalManagerDeploymentTemplate, err := template.New(kardinalManagerDeploymentTmplName).Parse(kardinalManagerDeploymentTmpl) + kardinalManagerDeploymentTemplate, err := template.New(kardinalManagerDeploymentTmplName).Parse(allKardinalTmpls) if err != nil { return stacktrace.Propagate(err, "An error occurred while parsing the kardinal-manager deployment template") } @@ -204,11 +216,12 @@ func DeployKardinalManagerInCluster(ctx context.Context, clusterResourcesURL str } templateDataObj := templateData{ - Namespace: kardinalNamespace, - ClusterResourcesURL: clusterResourcesURL, - KardinalAppIDLabelKey: consts.KardinalAppIDLabelKey, - KardinalManagerAppIDLabelValue: consts.KardinalManagerAppIDLabelValue, - KardinalManagerContainerImagePullPolicy: imagePullPolicy, + Namespace: kardinalNamespace, + ClusterResourcesURL: clusterResourcesURL, + KardinalAppIDLabelKey: consts.KardinalAppIDLabelKey, + KardinalManagerAppIDLabelValue: consts.KardinalManagerAppIDLabelValue, + KardinalManagerContainerImagePullPolicy: imagePullPolicy, + KardinalTraceRouterContainerImagePullPolicy: imagePullPolicy, } yamlFileContentsBuffer := &bytes.Buffer{} @@ -240,3 +253,27 @@ func RemoveKardinalManagerFromCluster(ctx context.Context) error { return nil } + +func GetKardinalTraceRouterManifest() (string, error) { + kardinalTraceRouterManifestTemplate, err := template.New(kardinalTraceRouterManifestTmplName).Parse(kardinalTraceRouterManifestTmpl) + if err != nil { + return "", stacktrace.Propagate(err, "An error occurred while parsing the Kardinal trace router manifest template") + } + + imagePullPolicy := "Always" + + templateDataObj := templateData{ + Namespace: kardinalNamespace, + KardinalAppIDLabelKey: consts.KardinalAppIDLabelKey, + KardinalManagerAppIDLabelValue: consts.KardinalManagerAppIDLabelValue, + KardinalTraceRouterContainerImagePullPolicy: imagePullPolicy, + } + + yamlFileContentsBuffer := &bytes.Buffer{} + + if err = kardinalTraceRouterManifestTemplate.Execute(yamlFileContentsBuffer, templateDataObj); err != nil { + return "", stacktrace.Propagate(err, "An error occurred while executing the template '%s' with data objects '%+v'", kardinalTraceRouterManifestTmplName, templateDataObj) + } + + return yamlFileContentsBuffer.String(), nil +}