From 5b9b5ff2c43c2a9238f40d906c4ffd71b72b3b60 Mon Sep 17 00:00:00 2001 From: Manuel Dewald Date: Fri, 7 Aug 2026 15:24:24 +0200 Subject: [PATCH 1/4] feat: Add persistant verbose flag * hide verbose tar output if not --verbose --- cli/cmd/build_image.go | 2 +- cli/cmd/build_image_test.go | 8 ++-- cli/cmd/build_images.go | 2 +- cli/cmd/build_images_test.go | 10 ++--- cli/cmd/extend_baseimage.go | 2 +- cli/cmd/extend_baseimage_test.go | 12 +++--- cli/cmd/k0s/install_k0s.go | 2 +- cli/cmd/k0s/install_k0s_test.go | 8 ++-- cli/cmd/root.go | 3 ++ cli/cmd/update_dockerfile.go | 2 +- cli/cmd/update_dockerfile_test.go | 14 +++---- cli/cmd/util/cmd_util.go | 1 + docs/README.md | 3 +- docs/oms.md | 3 +- docs/oms_add-cluster-admin.md | 6 +++ docs/oms_beta.md | 6 +++ docs/oms_beta_bootstrap-gcp.md | 6 +++ docs/oms_beta_bootstrap-gcp_cleanup.md | 6 +++ docs/oms_beta_bootstrap-gcp_postconfig.md | 6 +++ docs/oms_beta_bootstrap-gcp_restart-vms.md | 6 +++ docs/oms_beta_bootstrap-local.md | 6 +++ docs/oms_beta_extend.md | 6 +++ docs/oms_beta_extend_baseimage.md | 6 +++ docs/oms_beta_install.md | 6 +++ docs/oms_beta_install_argocd.md | 6 +++ docs/oms_beta_install_pc-apps.md | 6 +++ docs/oms_beta_vault-secret.md | 6 +++ docs/oms_build.md | 6 +++ docs/oms_build_image.md | 6 +++ docs/oms_build_images.md | 6 +++ docs/oms_create.md | 6 +++ docs/oms_create_test-user.md | 6 +++ docs/oms_download.md | 6 +++ docs/oms_download_k0s.md | 6 +++ docs/oms_download_package.md | 6 +++ docs/oms_init.md | 6 +++ docs/oms_init_install-config.md | 6 +++ docs/oms_install.md | 6 +++ docs/oms_install_codesphere.md | 6 +++ docs/oms_install_codesphere_dependencies.md | 1 + docs/oms_install_codesphere_infra.md | 1 + docs/oms_install_codesphere_platform.md | 1 + docs/oms_install_k0s.md | 6 +++ docs/oms_install_openbao.md | 6 +++ docs/oms_licenses.md | 6 +++ docs/oms_list.md | 6 +++ docs/oms_list_api-keys.md | 6 +++ docs/oms_list_packages.md | 6 +++ docs/oms_register.md | 6 +++ docs/oms_revoke.md | 6 +++ docs/oms_revoke_api-key.md | 6 +++ docs/oms_smoketest.md | 6 +++ docs/oms_smoketest_codesphere.md | 6 +++ docs/oms_template.md | 6 +++ docs/oms_template_config.md | 6 +++ docs/oms_update.md | 6 +++ docs/oms_update_api-key.md | 6 +++ docs/oms_update_dockerfile.md | 6 +++ docs/oms_update_install-config.md | 6 +++ docs/oms_update_oms.md | 6 +++ docs/oms_version.md | 6 +++ internal/bootstrap/local/installer.go | 4 +- internal/installer/codesphere.go | 6 +-- internal/installer/mocks.go | 44 +++++++++++++-------- internal/installer/package.go | 20 +++++----- internal/installer/package_test.go | 24 +++++------ internal/util/tar.go | 20 +++++----- 67 files changed, 372 insertions(+), 85 deletions(-) diff --git a/cli/cmd/build_image.go b/cli/cmd/build_image.go index b7be16acf..4bba0b99a 100644 --- a/cli/cmd/build_image.go +++ b/cli/cmd/build_image.go @@ -69,7 +69,7 @@ func AddBuildImageCmd(parentCmd *cobra.Command, opts *util.GlobalOptions) { // AddBuildImageCmd adds the build image command to the parent command func (c *BuildImageCmd) BuildImage(pm installer.PackageManager, im system.ImageManager) error { - err := pm.Extract(c.Opts.Force) + err := pm.Extract(c.Opts.Force, c.Opts.Verbose) if err != nil { return fmt.Errorf("failed to extract package: %w", err) } diff --git a/cli/cmd/build_image_test.go b/cli/cmd/build_image_test.go index cce1499ec..3fad27e1f 100644 --- a/cli/cmd/build_image_test.go +++ b/cli/cmd/build_image_test.go @@ -68,7 +68,7 @@ var _ = Describe("BuildImageCmd", func() { mockPackageManager := installer.NewMockPackageManager(GinkgoT()) mockImageManager := system.NewMockImageManager(GinkgoT()) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("", errors.New("failed to extract version")) err := c.BuildImage(mockPackageManager, mockImageManager) @@ -83,7 +83,7 @@ var _ = Describe("BuildImageCmd", func() { c.Opts.Dockerfile = "Dockerfile" c.Opts.Registry = "my-registry.com/my-image" - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("codesphere-v1.66.0", nil) mockImageManager.EXPECT().BuildImage("Dockerfile", "my-registry.com/my-image:codesphere-v1.66.0", ".").Return(errors.New("build failed")) @@ -99,7 +99,7 @@ var _ = Describe("BuildImageCmd", func() { c.Opts.Dockerfile = "Dockerfile" c.Opts.Registry = "my-registry.com/my-image" - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("codesphere-v1.66.0", nil) mockImageManager.EXPECT().BuildImage("Dockerfile", "my-registry.com/my-image:codesphere-v1.66.0", ".").Return(nil) mockImageManager.EXPECT().PushImage("my-registry.com/my-image:codesphere-v1.66.0").Return(errors.New("push failed")) @@ -116,7 +116,7 @@ var _ = Describe("BuildImageCmd", func() { c.Opts.Dockerfile = "Dockerfile" c.Opts.Registry = "my-registry.com/my-image" - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("codesphere-v1.66.0", nil) mockImageManager.EXPECT().BuildImage("Dockerfile", "my-registry.com/my-image:codesphere-v1.66.0", ".").Return(nil) mockImageManager.EXPECT().PushImage("my-registry.com/my-image:codesphere-v1.66.0").Return(nil) diff --git a/cli/cmd/build_images.go b/cli/cmd/build_images.go index 48cd3c4e4..c5448d3a6 100644 --- a/cli/cmd/build_images.go +++ b/cli/cmd/build_images.go @@ -76,7 +76,7 @@ func (c *BuildImagesCmd) BuildAndPushImages(pm installer.PackageManager, cm inst return fmt.Errorf("registry server (property registry.server) not defined in the config, please specify a valid registry to which the image shall be pushed") } - err = pm.Extract(c.Opts.Force) + err = pm.Extract(c.Opts.Force, c.Opts.Verbose) if err != nil { return fmt.Errorf("failed to extract package: %w", err) } diff --git a/cli/cmd/build_images_test.go b/cli/cmd/build_images_test.go index 9bf2e3b22..4c9a5cd94 100644 --- a/cli/cmd/build_images_test.go +++ b/cli/cmd/build_images_test.go @@ -198,7 +198,7 @@ var _ = Describe("BuildImagesCmd", func() { }, } mockConfigManager.EXPECT().ParseConfigYaml("config-without-dockerfile.yaml").Return(configWithoutDockerfile, nil) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("1.0.0", nil) err := c.BuildAndPushImages(mockPackageManager, mockConfigManager, mockImageManager) @@ -235,7 +235,7 @@ var _ = Describe("BuildImagesCmd", func() { }, } mockConfigManager.EXPECT().ParseConfigYaml("config-with-dockerfile.yaml").Return(configWithDockerfile, nil) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("1.0.0", nil) mockImageManager.EXPECT().BuildImage("Dockerfile", "registry.example.com/my-ubuntu-24.04-default:1.0.0", ".").Return(errors.New("build failed")) @@ -274,7 +274,7 @@ var _ = Describe("BuildImagesCmd", func() { }, } mockConfigManager.EXPECT().ParseConfigYaml("config-with-dockerfile.yaml").Return(configWithDockerfile, nil) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("1.0.0", nil) mockImageManager.EXPECT().BuildImage("Dockerfile", "registry.example.com/my-ubuntu-24.04-default:1.0.0", ".").Return(nil) mockImageManager.EXPECT().PushImage("registry.example.com/my-ubuntu-24.04-default:1.0.0").Return(errors.New("push failed")) @@ -314,7 +314,7 @@ var _ = Describe("BuildImagesCmd", func() { }, } mockConfigManager.EXPECT().ParseConfigYaml("config-with-dockerfile.yaml").Return(configWithDockerfile, nil) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("1.0.0", nil) mockImageManager.EXPECT().BuildImage("Dockerfile", "registry.example.com/my-ubuntu-24.04-default:1.0.0", ".").Return(nil) mockImageManager.EXPECT().PushImage("registry.example.com/my-ubuntu-24.04-default:1.0.0").Return(nil) @@ -371,7 +371,7 @@ var _ = Describe("BuildImagesCmd", func() { }, } mockConfigManager.EXPECT().ParseConfigYaml("config-with-multiple-images.yaml").Return(configWithMultipleImages, nil) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetCodesphereVersion().Return("1.0.0", nil) // Expect calls for my-ubuntu-24.04 default flavor diff --git a/cli/cmd/extend_baseimage.go b/cli/cmd/extend_baseimage.go index 3c2f3a0fc..4768a3df6 100644 --- a/cli/cmd/extend_baseimage.go +++ b/cli/cmd/extend_baseimage.go @@ -76,7 +76,7 @@ func AddExtendBaseimageCmd(extend *cobra.Command, opts *util.GlobalOptions) { } func (c *ExtendBaseimageCmd) ExtendBaseimage(pm installer.PackageManager, im system.ImageManager) error { - err := pm.Extract(c.Opts.Force) + err := pm.Extract(c.Opts.Force, c.Opts.Verbose) if err != nil { return fmt.Errorf("failed to extract package: %w", err) } diff --git a/cli/cmd/extend_baseimage_test.go b/cli/cmd/extend_baseimage_test.go index 8ebb274b0..3d1dfaef8 100644 --- a/cli/cmd/extend_baseimage_test.go +++ b/cli/cmd/extend_baseimage_test.go @@ -67,7 +67,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { mockPackageManager := installer.NewMockPackageManager(GinkgoT()) mockImageManager := system.NewMockImageManager(GinkgoT()) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("", errors.New("failed to get image name: extraction failed")) err := c.ExtendBaseimage(mockPackageManager, mockImageManager) @@ -79,7 +79,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { mockPackageManager := installer.NewMockPackageManager(GinkgoT()) mockImageManager := system.NewMockImageManager(GinkgoT()) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("", errors.New("failed to extract OCI image index: index extraction failed")) err := c.ExtendBaseimage(mockPackageManager, mockImageManager) @@ -91,7 +91,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { mockPackageManager := installer.NewMockPackageManager(GinkgoT()) mockImageManager := system.NewMockImageManager(GinkgoT()) - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("", errors.New("failed to read image tags: no image names found")) err := c.ExtendBaseimage(mockPackageManager, mockImageManager) @@ -110,7 +110,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { defer func() { _ = os.Remove(tempFile.Name()) }() defer func() { _ = tempFile.Close() }() - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04-base", nil) mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) @@ -127,7 +127,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { mockImageManager := system.NewMockImageManager(GinkgoT()) c.Opts.Force = true - mockPackageManager.EXPECT().Extract(true).Return(nil) + mockPackageManager.EXPECT().Extract(true, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("", errors.New("failed to extract package to workdir: extraction failed")) err := c.ExtendBaseimage(mockPackageManager, mockImageManager) @@ -146,7 +146,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { defer func() { _ = os.Remove(tempFile.Name()) }() defer func() { _ = tempFile.Close() }() - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04-base", nil) mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) diff --git a/cli/cmd/k0s/install_k0s.go b/cli/cmd/k0s/install_k0s.go index 56a28fdec..0bfd446c1 100644 --- a/cli/cmd/k0s/install_k0s.go +++ b/cli/cmd/k0s/install_k0s.go @@ -178,7 +178,7 @@ func (c *InstallK0sCmd) getK0sBinaryPath(pm installer.PackageManager, k0s instal } if c.Opts.Package != "" { - if err := pm.ExtractDependency(defaultK0sPath, c.Opts.Force); err != nil { + if err := pm.ExtractDependency(defaultK0sPath, c.Opts.Force, c.Opts.Verbose); err != nil { return "", fmt.Errorf("failed to extract k0s from package: %w", err) } return pm.GetDependencyPath(defaultK0sPath), nil diff --git a/cli/cmd/k0s/install_k0s_test.go b/cli/cmd/k0s/install_k0s_test.go index 0c46fe437..7116d4fb5 100644 --- a/cli/cmd/k0s/install_k0s_test.go +++ b/cli/cmd/k0s/install_k0s_test.go @@ -167,7 +167,7 @@ var _ = Describe("InstallK0sCmd", func() { mockEnv.EXPECT().GetOmsWorkdir().Return(tempDir) mockFileWriter.EXPECT().MkdirAll(tempDir, os.FileMode(0755)).Return(nil) - mockPM.EXPECT().ExtractDependency("kubernetes/files/k0s", true).Return(nil) + mockPM.EXPECT().ExtractDependency("kubernetes/files/k0s", true, false).Return(nil) mockPM.EXPECT().GetDependencyPath("kubernetes/files/k0s").Return("/test/path/k0s") mockK0sctl.EXPECT().Download("", true, false).Return("/tmp/k0sctl", nil) mockFileWriter.EXPECT().WriteFile(mock.Anything, mock.Anything, mock.Anything).Return(nil) @@ -214,7 +214,7 @@ var _ = Describe("InstallK0sCmd", func() { mockEnv.EXPECT().GetOmsWorkdir().Return(tempDir) mockFileWriter.EXPECT().MkdirAll(tempDir, os.FileMode(0755)).Return(nil) - mockPM.EXPECT().ExtractDependency("kubernetes/files/k0s", false).Return(nil) + mockPM.EXPECT().ExtractDependency("kubernetes/files/k0s", false, false).Return(nil) mockPM.EXPECT().GetDependencyPath("kubernetes/files/k0s").Return("/test/path/k0s") mockK0sctl.EXPECT().Download("", false, false).Return("", os.ErrPermission) @@ -230,7 +230,7 @@ var _ = Describe("InstallK0sCmd", func() { mockEnv.EXPECT().GetOmsWorkdir().Return(tempDir) mockFileWriter.EXPECT().MkdirAll(tempDir, os.FileMode(0755)).Return(nil) - mockPM.EXPECT().ExtractDependency("kubernetes/files/k0s", false).Return(nil) + mockPM.EXPECT().ExtractDependency("kubernetes/files/k0s", false, false).Return(nil) mockPM.EXPECT().GetDependencyPath("kubernetes/files/k0s").Return("/test/path/k0s") mockK0sctl.EXPECT().Download("", false, false).Return("/tmp/k0sctl", nil) mockFileWriter.EXPECT().WriteFile(mock.Anything, mock.Anything, mock.Anything).Return(nil) @@ -243,7 +243,7 @@ var _ = Describe("InstallK0sCmd", func() { setupCommonMocks := func() { mockEnv.EXPECT().GetOmsWorkdir().Return(tempDir) - mockPM.EXPECT().ExtractDependency("kubernetes/files/k0s", false).Return(nil) + mockPM.EXPECT().ExtractDependency("kubernetes/files/k0s", false, false).Return(nil) mockPM.EXPECT().GetDependencyPath("kubernetes/files/k0s").Return("/test/path/k0s") mockK0sctl.EXPECT().Download("", false, false).Return("/tmp/k0sctl", nil) mockK0sctl.EXPECT().Apply(mock.Anything, "/tmp/k0sctl", false).Return(nil) diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 591b1c8b0..25511ccf8 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -53,6 +53,9 @@ func GetRootCmd() *cobra.Command { } }, } + + rootCmd.PersistentFlags().BoolVarP(&opts.Verbose, "verbose", "", false, "Enable verbose output") + // General commands AddVersionCmd(rootCmd) AddBetaCmd(rootCmd, opts) diff --git a/cli/cmd/update_dockerfile.go b/cli/cmd/update_dockerfile.go index 601362ae7..fe3325780 100644 --- a/cli/cmd/update_dockerfile.go +++ b/cli/cmd/update_dockerfile.go @@ -82,7 +82,7 @@ in the specified Dockerfile to use that base image. The base image is loaded int } func (c *UpdateDockerfileCmd) UpdateDockerfile(pm installer.PackageManager, im system.ImageManager, args []string) error { - err := pm.Extract(c.Opts.Force) + err := pm.Extract(c.Opts.Force, c.Opts.Verbose) if err != nil { return fmt.Errorf("failed to extract package: %w", err) } diff --git a/cli/cmd/update_dockerfile_test.go b/cli/cmd/update_dockerfile_test.go index 0505197b3..ca6c9ee2a 100644 --- a/cli/cmd/update_dockerfile_test.go +++ b/cli/cmd/update_dockerfile_test.go @@ -88,7 +88,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { c.Opts.Baseimage = "workspace-agent-24.04.tar" c.Opts.Force = false - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("workspace-agent-24.04.tar").Return("", errors.New("failed to extract image")) err := c.UpdateDockerfile(mockPackageManager, mockImageManager, []string{}) @@ -105,7 +105,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { c.Opts.Baseimage = "" c.Opts.Force = false - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04", nil) mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockImageManager.EXPECT().LoadImage("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar").Return(nil) @@ -125,7 +125,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { c.Opts.Baseimage = "" c.Opts.Force = false - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04", nil) mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockImageManager.EXPECT().LoadImage("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar").Return(errors.New("load failed")) @@ -156,7 +156,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { c.Opts.Baseimage = "" c.Opts.Force = false - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04", nil) mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockImageManager.EXPECT().LoadImage("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar").Return(nil) @@ -190,7 +190,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { c.Opts.Baseimage = "" c.Opts.Force = false - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04", nil) mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) @@ -223,7 +223,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { c.Opts.Baseimage = "workspace-agent-20.04.tar" c.Opts.Force = true - mockPackageManager.EXPECT().Extract(true).Return(nil) + mockPackageManager.EXPECT().Extract(true, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("workspace-agent-20.04.tar").Return("ubuntu:20.04", nil) mockPackageManager.EXPECT().GetBaseimagePath("workspace-agent-20.04.tar", true).Return("/test/workdir/deps/codesphere/images/workspace-agent-20.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) @@ -256,7 +256,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { c.Opts.Baseimage = "workspace-agent-24.04.tar" c.Opts.Force = false - mockPackageManager.EXPECT().Extract(false).Return(nil) + mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("workspace-agent-24.04.tar").Return("registry.example.com/workspace-agent:24.04", nil) mockPackageManager.EXPECT().GetBaseimagePath("workspace-agent-24.04.tar", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) diff --git a/cli/cmd/util/cmd_util.go b/cli/cmd/util/cmd_util.go index 120706bd0..7ba5a8901 100644 --- a/cli/cmd/util/cmd_util.go +++ b/cli/cmd/util/cmd_util.go @@ -16,4 +16,5 @@ func AddCmd(parent *cobra.Command, cmd *cobra.Command) { type GlobalOptions struct { OmsPortalApiKey string + Verbose bool } diff --git a/docs/README.md b/docs/README.md index dbbe2f036..2d6430393 100644 --- a/docs/README.md +++ b/docs/README.md @@ -12,7 +12,8 @@ like downloading new versions. ### Options ``` - -h, --help help for oms + -h, --help help for oms + --verbose Enable verbose output ``` ### SEE ALSO diff --git a/docs/oms.md b/docs/oms.md index dbbe2f036..2d6430393 100644 --- a/docs/oms.md +++ b/docs/oms.md @@ -12,7 +12,8 @@ like downloading new versions. ### Options ``` - -h, --help help for oms + -h, --help help for oms + --verbose Enable verbose output ``` ### SEE ALSO diff --git a/docs/oms_add-cluster-admin.md b/docs/oms_add-cluster-admin.md index 622ff73be..72edb37a0 100644 --- a/docs/oms_add-cluster-admin.md +++ b/docs/oms_add-cluster-admin.md @@ -36,6 +36,12 @@ $ oms add-cluster-admin --email admin@codesphere.com --namespace kube-system --s --secret-name string Name of the Kubernetes secret holding the cluster admin email (default "cluster-admin-email") ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms](oms.md) - Codesphere Operations Management System (OMS) diff --git a/docs/oms_beta.md b/docs/oms_beta.md index 3e19c4f21..194818c1c 100644 --- a/docs/oms_beta.md +++ b/docs/oms_beta.md @@ -13,6 +13,12 @@ Be aware that that usage and behavior may change as the features are developed. -h, --help help for beta ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms](oms.md) - Codesphere Operations Management System (OMS) diff --git a/docs/oms_beta_bootstrap-gcp.md b/docs/oms_beta_bootstrap-gcp.md index fd6e88e75..38568c229 100644 --- a/docs/oms_beta_bootstrap-gcp.md +++ b/docs/oms_beta_bootstrap-gcp.md @@ -88,6 +88,12 @@ oms beta bootstrap-gcp [flags] --zone string GCP Zone (default: europe-west4-a) (default "europe-west4-a") ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta](oms_beta.md) - Commands for early testing diff --git a/docs/oms_beta_bootstrap-gcp_cleanup.md b/docs/oms_beta_bootstrap-gcp_cleanup.md index 09d870225..940597889 100644 --- a/docs/oms_beta_bootstrap-gcp_cleanup.md +++ b/docs/oms_beta_bootstrap-gcp_cleanup.md @@ -42,6 +42,12 @@ $ oms beta bootstrap-gcp cleanup --project-id my-project --base-domain example.c --skip-dns-cleanup Skip cleaning up DNS records ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta bootstrap-gcp](oms_beta_bootstrap-gcp.md) - Bootstrap GCP infrastructure for Codesphere diff --git a/docs/oms_beta_bootstrap-gcp_postconfig.md b/docs/oms_beta_bootstrap-gcp_postconfig.md index e4bfa2652..2a8807bfc 100644 --- a/docs/oms_beta_bootstrap-gcp_postconfig.md +++ b/docs/oms_beta_bootstrap-gcp_postconfig.md @@ -21,6 +21,12 @@ oms beta bootstrap-gcp postconfig [flags] --private-key-path string Path to the GCP service account private key file (optional) ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta bootstrap-gcp](oms_beta_bootstrap-gcp.md) - Bootstrap GCP infrastructure for Codesphere diff --git a/docs/oms_beta_bootstrap-gcp_restart-vms.md b/docs/oms_beta_bootstrap-gcp_restart-vms.md index 9eeb152ef..5599394ac 100644 --- a/docs/oms_beta_bootstrap-gcp_restart-vms.md +++ b/docs/oms_beta_bootstrap-gcp_restart-vms.md @@ -43,6 +43,12 @@ $ oms beta bootstrap-gcp restart-vms --project-id my-project --zone us-central1- --zone string GCP Zone (optional, will use infra file if not provided) ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta bootstrap-gcp](oms_beta_bootstrap-gcp.md) - Bootstrap GCP infrastructure for Codesphere diff --git a/docs/oms_beta_bootstrap-local.md b/docs/oms_beta_bootstrap-local.md index 4a78c9a07..c75b4f9d6 100644 --- a/docs/oms_beta_bootstrap-local.md +++ b/docs/oms_beta_bootstrap-local.md @@ -37,6 +37,12 @@ oms beta bootstrap-local [flags] -y, --yes Auto-approve the local bootstrapping warning prompt ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta](oms_beta.md) - Commands for early testing diff --git a/docs/oms_beta_extend.md b/docs/oms_beta_extend.md index b4dff5a9a..e5ee19117 100644 --- a/docs/oms_beta_extend.md +++ b/docs/oms_beta_extend.md @@ -12,6 +12,12 @@ Extend Codesphere ressources such as base images to customize them for your need -h, --help help for extend ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta](oms_beta.md) - Commands for early testing diff --git a/docs/oms_beta_extend_baseimage.md b/docs/oms_beta_extend_baseimage.md index fb369e7b9..299ca1c56 100644 --- a/docs/oms_beta_extend_baseimage.md +++ b/docs/oms_beta_extend_baseimage.md @@ -24,6 +24,12 @@ oms beta extend baseimage [flags] -p, --package string Package file (e.g. codesphere-v1.2.3-installer.tar.gz) to load base image from ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta extend](oms_beta_extend.md) - Extend Codesphere ressources such as base images. diff --git a/docs/oms_beta_install.md b/docs/oms_beta_install.md index 0f5404568..c0a2a6b67 100644 --- a/docs/oms_beta_install.md +++ b/docs/oms_beta_install.md @@ -8,6 +8,12 @@ Install beta components -h, --help help for install ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta](oms_beta.md) - Commands for early testing diff --git a/docs/oms_beta_install_argocd.md b/docs/oms_beta_install_argocd.md index 6df7f0052..ba0ef5d99 100644 --- a/docs/oms_beta_install_argocd.md +++ b/docs/oms_beta_install_argocd.md @@ -53,6 +53,12 @@ $ oms beta install argocd --deploy-dc-config --dc-id 0 -v, --version string Version of the ArgoCD helm chart to install ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta install](oms_beta_install.md) - Install beta components diff --git a/docs/oms_beta_install_pc-apps.md b/docs/oms_beta_install_pc-apps.md index cd1b71070..d812b052f 100644 --- a/docs/oms_beta_install_pc-apps.md +++ b/docs/oms_beta_install_pc-apps.md @@ -45,6 +45,12 @@ $ oms beta install pc-apps --version 1.0.0 --force-conflicts --version string Chart version to reference as the Application target revision (required) ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta install](oms_beta_install.md) - Install beta components diff --git a/docs/oms_beta_vault-secret.md b/docs/oms_beta_vault-secret.md index 268a8d0d4..8082e65f3 100644 --- a/docs/oms_beta_vault-secret.md +++ b/docs/oms_beta_vault-secret.md @@ -33,6 +33,12 @@ $ oms vault-secret --vault-file prod.vault.yaml --age-key /path/to/age_key.txt - --vault-file string Path to the SOPS-encrypted vault file (required) ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms beta](oms_beta.md) - Commands for early testing diff --git a/docs/oms_build.md b/docs/oms_build.md index f5602baea..b6d405f42 100644 --- a/docs/oms_build.md +++ b/docs/oms_build.md @@ -12,6 +12,12 @@ Build and push container images to a registry using the provided configuration. -h, --help help for build ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms](oms.md) - Codesphere Operations Management System (OMS) diff --git a/docs/oms_build_image.md b/docs/oms_build_image.md index ce746c1d0..45fd57dfe 100644 --- a/docs/oms_build_image.md +++ b/docs/oms_build_image.md @@ -28,6 +28,12 @@ $ oms build image --dockerfile baseimage/Dockerfile --package codesphere-v1.68.0 -r, --registry string Registry URL to push to (e.g., my-registry.com/my-image) (required) ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms build](oms_build.md) - Build and push images to a registry diff --git a/docs/oms_build_images.md b/docs/oms_build_images.md index 5a08ee8c6..36ed57ed4 100644 --- a/docs/oms_build_images.md +++ b/docs/oms_build_images.md @@ -19,6 +19,12 @@ oms build images [flags] -h, --help help for images ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms build](oms_build.md) - Build and push images to a registry diff --git a/docs/oms_create.md b/docs/oms_create.md index 424aceb40..582e6d15c 100644 --- a/docs/oms_create.md +++ b/docs/oms_create.md @@ -12,6 +12,12 @@ Create resources for Codesphere installations, such as test users for automated -h, --help help for create ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms](oms.md) - Codesphere Operations Management System (OMS) diff --git a/docs/oms_create_test-user.md b/docs/oms_create_test-user.md index 0e1555ed3..f5a77570a 100644 --- a/docs/oms_create_test-user.md +++ b/docs/oms_create_test-user.md @@ -33,6 +33,12 @@ oms create test-user [flags] --ssl-mode string PostgreSQL SSL mode (default "disable") ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms create](oms_create.md) - Create resources for Codesphere diff --git a/docs/oms_download.md b/docs/oms_download.md index 388ab6a8f..2adc5752f 100644 --- a/docs/oms_download.md +++ b/docs/oms_download.md @@ -13,6 +13,12 @@ e.g. available Codesphere packages -h, --help help for download ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms](oms.md) - Codesphere Operations Management System (OMS) diff --git a/docs/oms_download_k0s.md b/docs/oms_download_k0s.md index b3cbdfc9e..9e74e770e 100644 --- a/docs/oms_download_k0s.md +++ b/docs/oms_download_k0s.md @@ -37,6 +37,12 @@ $ oms download k0s --force -v, --version string Version of k0s to download ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms download](oms_download.md) - Download resources available through OMS diff --git a/docs/oms_download_package.md b/docs/oms_download_package.md index a9d12498e..99b2b3b1b 100644 --- a/docs/oms_download_package.md +++ b/docs/oms_download_package.md @@ -35,6 +35,12 @@ $ oms download package --version codesphere-v1.55.0 --file installer-lite.tar.gz -V, --version string Codesphere version to download ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms download](oms_download.md) - Download resources available through OMS diff --git a/docs/oms_init.md b/docs/oms_init.md index c249acca7..cc0adf89b 100644 --- a/docs/oms_init.md +++ b/docs/oms_init.md @@ -12,6 +12,12 @@ Initialize configuration files for Codesphere installation and other components. -h, --help help for init ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms](oms.md) - Codesphere Operations Management System (OMS) diff --git a/docs/oms_init_install-config.md b/docs/oms_init_install-config.md index ee0db9690..f4152e6c7 100644 --- a/docs/oms_init_install-config.md +++ b/docs/oms_init_install-config.md @@ -93,6 +93,12 @@ $ oms init install-config --validate -c config.yaml --vault prod.vault.yaml --with-comments Add helpful comments to the generated YAML files ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms init](oms_init.md) - Initialize configuration files diff --git a/docs/oms_install.md b/docs/oms_install.md index 21543f1d6..fd4c54f89 100644 --- a/docs/oms_install.md +++ b/docs/oms_install.md @@ -12,6 +12,12 @@ Install Codesphere and other components like Ceph and PostgreSQL. -h, --help help for install ``` +### Options inherited from parent commands + +``` + --verbose Enable verbose output +``` + ### SEE ALSO * [oms](oms.md) - Codesphere Operations Management System (OMS) diff --git a/docs/oms_install_codesphere.md b/docs/oms_install_codesphere.md index dcf6c2148..97be165dd 100644 --- a/docs/oms_install_codesphere.md +++ b/docs/oms_install_codesphere.md @@ -43,6 +43,12 @@ $ oms install codesphere -p codesphere-v1.2.3-installer-lite.tar.gz -k Date: Thu, 13 Aug 2026 11:23:45 +0200 Subject: [PATCH 2/4] fix: propagate verbose output --- cli/cmd/beta.go | 2 +- cli/cmd/bootstrap_local.go | 6 +- cli/cmd/codesphere/install_codesphere.go | 3 + .../install_codesphere_dependencies.go | 1 + .../codesphere/install_codesphere_infra.go | 1 + .../codesphere/install_codesphere_platform.go | 1 + cli/cmd/codesphere/smoketest_codesphere.go | 12 ++-- .../codesphere/smoketest_codesphere_test.go | 2 +- cli/cmd/download_package.go | 5 +- cli/cmd/download_package_test.go | 12 ++-- cli/cmd/extend_baseimage.go | 2 +- cli/cmd/extend_baseimage_test.go | 4 +- cli/cmd/k0s/download_k0s.go | 5 +- cli/cmd/k0s/download_k0s_test.go | 9 ++- cli/cmd/update_dockerfile.go | 2 +- cli/cmd/update_dockerfile_test.go | 12 ++-- docs/oms_download_k0s.md | 4 -- docs/oms_download_package.md | 1 - docs/oms_smoketest_codesphere.md | 4 -- internal/bootstrap/local/installer.go | 4 +- internal/bootstrap/local/local.go | 4 +- internal/codesphere/teststeps/step.go | 8 +-- internal/installer/codesphere.go | 8 ++- internal/installer/codesphere_test.go | 27 +++++++++ internal/installer/mocks.go | 60 +++++++++++-------- internal/installer/package.go | 12 ++-- internal/installer/package_test.go | 24 ++++---- internal/util/tar.go | 19 +++--- internal/util/tar_test.go | 44 +++++++++++++- 29 files changed, 186 insertions(+), 112 deletions(-) diff --git a/cli/cmd/beta.go b/cli/cmd/beta.go index 5fed327b2..ec7afd9e3 100644 --- a/cli/cmd/beta.go +++ b/cli/cmd/beta.go @@ -26,7 +26,7 @@ func AddBetaCmd(rootCmd *cobra.Command, opts *util.GlobalOptions) { AddExtendCmd(beta.cmd, opts) AddBootstrapGcpCmd(beta.cmd, opts) - AddBootstrapLocalCmd(beta.cmd) + AddBootstrapLocalCmd(beta.cmd, opts) AddBetaInstallCmd(beta.cmd, opts) AddBetaVaultSecretCmd(beta.cmd, opts) } diff --git a/cli/cmd/bootstrap_local.go b/cli/cmd/bootstrap_local.go index 19c4fb9fd..b27bda67a 100644 --- a/cli/cmd/bootstrap_local.go +++ b/cli/cmd/bootstrap_local.go @@ -39,6 +39,7 @@ import ( type BootstrapLocalCmd struct { cmd *cobra.Command + Opts *util.GlobalOptions CodesphereEnv *local.CodesphereEnvironment Yes bool // Experiments backs the deprecated --experiments flag; its values @@ -56,7 +57,7 @@ func (c *BootstrapLocalCmd) RunE(_ *cobra.Command, args []string) error { return nil } -func AddBootstrapLocalCmd(parent *cobra.Command) { +func AddBootstrapLocalCmd(parent *cobra.Command, opts *util.GlobalOptions) { bootstrapLocalCmd := BootstrapLocalCmd{ cmd: &cobra.Command{ Use: "bootstrap-local", @@ -66,6 +67,7 @@ func AddBootstrapLocalCmd(parent *cobra.Command) { For local setups, use Minikube with a virtual machine on Linux. Not for production use.`), }, + Opts: opts, CodesphereEnv: &local.CodesphereEnvironment{}, } @@ -153,7 +155,7 @@ func (c *BootstrapLocalCmd) BootstrapLocal() error { return fmt.Errorf("failed to initialize Helm client: %w", err) } - bs := local.NewLocalBootstrapper(ctx, stlog, kubeClient, restConfig, fw, icg, helmClient, c.CodesphereEnv) + bs := local.NewLocalBootstrapper(ctx, stlog, kubeClient, restConfig, fw, icg, helmClient, c.CodesphereEnv, c.Opts.Verbose) return bs.Bootstrap() } diff --git a/cli/cmd/codesphere/install_codesphere.go b/cli/cmd/codesphere/install_codesphere.go index 141bf27b9..6dad6803d 100644 --- a/cli/cmd/codesphere/install_codesphere.go +++ b/cli/cmd/codesphere/install_codesphere.go @@ -65,14 +65,17 @@ func (c *InstallCodesphereCmd) RunE(cmd *cobra.Command, _ []string) error { infraInstaller := &installer.CodesphereInstaller{ SkipSteps: c.Opts.SkipSteps, AllowedSteps: installer.InfraSteps, + Verbose: c.Opts.Verbose, } dependenciesInstaller := &installer.CodesphereInstaller{ SkipSteps: append(sharedInstallCodesphereSteps(), c.Opts.SkipSteps...), AllowedSteps: installer.DependenciesSteps, + Verbose: c.Opts.Verbose, } platformInstaller := &installer.CodesphereInstaller{ SkipSteps: append(sharedInstallCodesphereSteps(), c.Opts.SkipSteps...), AllowedSteps: installer.PlatformSteps, + Verbose: c.Opts.Verbose, } if c.Opts.CodesphereOnly { diff --git a/cli/cmd/codesphere/install_codesphere_dependencies.go b/cli/cmd/codesphere/install_codesphere_dependencies.go index 62f47ac8d..73cb2bc49 100644 --- a/cli/cmd/codesphere/install_codesphere_dependencies.go +++ b/cli/cmd/codesphere/install_codesphere_dependencies.go @@ -54,6 +54,7 @@ func installCodesphereDepencies(opts *InstallCodesphereOpts, cfg files.RootConfi VaultPath: opts.Vault, PrivKey: opts.PrivKey, Force: opts.Force, + Verbose: opts.Verbose, SkipSteps: opts.SkipSteps, AllowedSteps: installer.DependenciesSteps, DirectConnection: opts.DirectConnection, diff --git a/cli/cmd/codesphere/install_codesphere_infra.go b/cli/cmd/codesphere/install_codesphere_infra.go index 70274e9bf..e30ff730e 100644 --- a/cli/cmd/codesphere/install_codesphere_infra.go +++ b/cli/cmd/codesphere/install_codesphere_infra.go @@ -44,6 +44,7 @@ func installCodesphereInfra(opts *InstallCodesphereOpts, env env.Env) error { VaultPath: opts.Vault, PrivKey: opts.PrivKey, Force: opts.Force, + Verbose: opts.Verbose, SkipSteps: opts.SkipSteps, AllowedSteps: installer.InfraSteps, DirectConnection: opts.DirectConnection, diff --git a/cli/cmd/codesphere/install_codesphere_platform.go b/cli/cmd/codesphere/install_codesphere_platform.go index 7b9a7c3e8..514efd2aa 100644 --- a/cli/cmd/codesphere/install_codesphere_platform.go +++ b/cli/cmd/codesphere/install_codesphere_platform.go @@ -49,6 +49,7 @@ func installCodespherePlatform(ctx context.Context, opts *InstallCodesphereOpts, VaultPath: opts.Vault, PrivKey: opts.PrivKey, Force: opts.Force, + Verbose: opts.Verbose, SkipSteps: opts.SkipSteps, AllowedSteps: installer.PlatformSteps, CodesphereOnly: true, diff --git a/cli/cmd/codesphere/smoketest_codesphere.go b/cli/cmd/codesphere/smoketest_codesphere.go index 54425365b..01d716be8 100644 --- a/cli/cmd/codesphere/smoketest_codesphere.go +++ b/cli/cmd/codesphere/smoketest_codesphere.go @@ -33,7 +33,8 @@ var availableSteps = []teststeps.SmokeTestStep{ } type SmoketestCodesphereCmd struct { - cmd *cobra.Command + cmd *cobra.Command + GlobalOptions *util.GlobalOptions // TODO (Simon)for now I kept the opts in the teststeps package, // but if we add more tests we should move unified opts here and probably use seperate // structs for the different test types (base smoke test, ui test etc.) @@ -41,6 +42,7 @@ type SmoketestCodesphereCmd struct { } func (c *SmoketestCodesphereCmd) RunE(_ *cobra.Command, args []string) error { + c.Opts.Verbose = c.GlobalOptions.Verbose client, err := codesphere.NewClient(c.Opts.BaseURL, c.Opts.Token) if err != nil { return fmt.Errorf("failed to create Codesphere client: %w", err) @@ -76,10 +78,6 @@ func AddSmoketestCmd(parent *cobra.Command, opts *util.GlobalOptions) { Cmd: "--baseurl https://codesphere.example.com/api --token YOUR_TOKEN --team-id TEAM_ID --plan-id PLAN_ID", Desc: "Run smoke tests against a specific team within your Codesphere installation, using a specific workspace plan", }, - { - Cmd: "--baseurl https://codesphere.example.com/api --token YOUR_TOKEN --quiet", - Desc: "Run smoke tests in quiet mode (no progress logging)", - }, { Cmd: "--baseurl https://codesphere.example.com/api --token YOUR_TOKEN --timeout 15m", Desc: "Run smoke tests with custom timeout", @@ -94,13 +92,13 @@ func AddSmoketestCmd(parent *cobra.Command, opts *util.GlobalOptions) { }, }), }, - Opts: &teststeps.SmoketestCodesphereOpts{}, + GlobalOptions: opts, + Opts: &teststeps.SmoketestCodesphereOpts{}, } c.cmd.Flags().StringVar(&c.Opts.BaseURL, "baseurl", "", "Base URL of the Codesphere API") c.cmd.Flags().StringVar(&c.Opts.Token, "token", "", "API token for authentication") c.cmd.Flags().StringVar(&c.Opts.TeamID, "team-id", "", "Team ID for workspace creation") c.cmd.Flags().StringVar(&c.Opts.PlanID, "plan-id", "", "Plan ID for workspace creation") - c.cmd.Flags().BoolVarP(&c.Opts.Quiet, "quiet", "q", false, "Suppress progress logging") c.cmd.Flags().DurationVar(&c.Opts.Timeout, "timeout", defaultTimeout, "Timeout for the entire smoke test") c.cmd.Flags().StringVar(&c.Opts.Profile, "profile", defaultProfile, "CI profile to use for landscape and pipeline") c.cmd.Flags().StringSliceVar(&c.Opts.Steps, "steps", []string{}, fmt.Sprintf("Comma-separated list of steps to run (%s). If empty, all steps including deleteWorkspace are run. If specified without deleteWorkspace, the workspace will be kept for manual inspection.", strings.Join(stepNames, ","))) diff --git a/cli/cmd/codesphere/smoketest_codesphere_test.go b/cli/cmd/codesphere/smoketest_codesphere_test.go index e740356e2..4c2a02569 100644 --- a/cli/cmd/codesphere/smoketest_codesphere_test.go +++ b/cli/cmd/codesphere/smoketest_codesphere_test.go @@ -100,7 +100,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() { Token: "test-token", TeamID: teamId, PlanID: planId, - Quiet: true, // Suppress log output in tests + Verbose: false, // Suppress log output in tests Timeout: 10 * time.Minute, Profile: "ci.yml", Steps: []string{}, diff --git a/cli/cmd/download_package.go b/cli/cmd/download_package.go index fa671a2bc..e53e2f487 100644 --- a/cli/cmd/download_package.go +++ b/cli/cmd/download_package.go @@ -27,7 +27,6 @@ type DownloadPackageOpts struct { Version string Hash string Filename string - Quiet bool } func (c *DownloadPackageCmd) RunE(_ *cobra.Command, args []string) error { @@ -83,13 +82,13 @@ func AddDownloadPackageCmd(download *cobra.Command, opts *util.GlobalOptions) { return nil }, }, + Opts: DownloadPackageOpts{GlobalOptions: opts}, FileWriter: intutil.NewFilesystemWriter(), } pkg.cmd.Flags().StringVarP(&pkg.Opts.Version, "version", "V", "", "Codesphere version to download") pkg.cmd.Flags().StringVarP(&pkg.Opts.Hash, "hash", "H", "", "Hash of the version to download if multiple builds exist for the same version") pkg.cmd.Flags().StringVarP(&pkg.Opts.Filename, "file", "f", "installer-lite.tar.gz", "Specify artifact to download") - pkg.cmd.Flags().BoolVarP(&pkg.Opts.Quiet, "quiet", "q", false, "Suppress progress output during download") util.AddCmd(download, pkg.cmd) pkg.cmd.RunE = pkg.RunE @@ -118,7 +117,7 @@ func (c *DownloadPackageCmd) DownloadBuild(p portal.Portal, build portal.Build, fileSize = int(fileInfo.Size()) } - err = p.DownloadBuildArtifact("codesphere", download, out, fileSize, c.Opts.Quiet) + err = p.DownloadBuildArtifact("codesphere", download, out, fileSize, !c.Opts.Verbose) if err != nil { return fmt.Errorf("failed to download build: %w", err) } diff --git a/cli/cmd/download_package_test.go b/cli/cmd/download_package_test.go index c38fe1dc8..d2a3090db 100644 --- a/cli/cmd/download_package_test.go +++ b/cli/cmd/download_package_test.go @@ -39,9 +39,9 @@ var _ = Describe("DownloadPackages", func() { JustBeforeEach(func() { c = cmd.DownloadPackageCmd{ Opts: cmd.DownloadPackageOpts{ - Version: version, - Filename: filename, - Quiet: false, + GlobalOptions: &util.GlobalOptions{}, + Version: version, + Filename: filename, }, FileWriter: mockFileWriter, } @@ -182,7 +182,7 @@ var _ = Describe("DownloadPackages", func() { fakeFile := os.NewFile(uintptr(0), filename) mockFileWriter.EXPECT().OpenAppend(version+"-"+hash+"-"+filename).Return(fakeFile, nil) mockFileWriter.EXPECT().Open(version+"-"+hash+"-"+filename).Return(fakeFile, nil) - mockPortal.EXPECT().DownloadBuildArtifact(portal.CodesphereProduct, expectedBuildToDownload, mock.Anything, 0, false).Return(nil) + mockPortal.EXPECT().DownloadBuildArtifact(portal.CodesphereProduct, expectedBuildToDownload, mock.Anything, 0, true).Return(nil) mockPortal.EXPECT().VerifyBuildArtifactDownload(mock.Anything, expectedBuildToDownload).Return(nil) err := c.DownloadBuild(mockPortal, build, filename) Expect(err).NotTo(HaveOccurred()) @@ -209,7 +209,7 @@ var _ = Describe("DownloadPackages", func() { fakeFile := os.NewFile(uintptr(0), filename) mockFileWriter.EXPECT().OpenAppend(version+"-"+longHash+"-"+filename).Return(fakeFile, nil) mockFileWriter.EXPECT().Open(version+"-"+longHash+"-"+filename).Return(fakeFile, nil) - mockPortal.EXPECT().DownloadBuildArtifact(portal.CodesphereProduct, expectedBuildToDownload, mock.Anything, 0, false).Return(nil) + mockPortal.EXPECT().DownloadBuildArtifact(portal.CodesphereProduct, expectedBuildToDownload, mock.Anything, 0, true).Return(nil) mockPortal.EXPECT().VerifyBuildArtifactDownload(mock.Anything, expectedBuildToDownload).Return(nil) err := c.DownloadBuild(mockPortal, buildWithLongHash, filename) Expect(err).NotTo(HaveOccurred()) @@ -231,7 +231,7 @@ var _ = Describe("DownloadPackages", func() { fakeFile := os.NewFile(uintptr(0), filename) mockFileWriter.EXPECT().OpenAppend("other-version-v1.42.0-"+hash+"-"+filename).Return(fakeFile, nil) mockFileWriter.EXPECT().Open("other-version-v1.42.0-"+hash+"-"+filename).Return(fakeFile, nil) - mockPortal.EXPECT().DownloadBuildArtifact(portal.CodesphereProduct, expectedBuildToDownload, mock.Anything, 0, false).Return(nil) + mockPortal.EXPECT().DownloadBuildArtifact(portal.CodesphereProduct, expectedBuildToDownload, mock.Anything, 0, true).Return(nil) mockPortal.EXPECT().VerifyBuildArtifactDownload(mock.Anything, expectedBuildToDownload).Return(nil) err := c.DownloadBuild(mockPortal, build, filename) Expect(err).NotTo(HaveOccurred()) diff --git a/cli/cmd/extend_baseimage.go b/cli/cmd/extend_baseimage.go index 4768a3df6..78020ea16 100644 --- a/cli/cmd/extend_baseimage.go +++ b/cli/cmd/extend_baseimage.go @@ -86,7 +86,7 @@ func (c *ExtendBaseimageCmd) ExtendBaseimage(pm installer.PackageManager, im sys return fmt.Errorf("failed to get image name: %w", err) } - imagePath, err := pm.GetBaseimagePath(c.Opts.Baseimage, c.Opts.Force) + imagePath, err := pm.GetBaseimagePath(c.Opts.Baseimage, c.Opts.Force, c.Opts.Verbose) if err != nil { return fmt.Errorf("failed to get image path: %w", err) } diff --git a/cli/cmd/extend_baseimage_test.go b/cli/cmd/extend_baseimage_test.go index 3d1dfaef8..d7e7e2ac7 100644 --- a/cli/cmd/extend_baseimage_test.go +++ b/cli/cmd/extend_baseimage_test.go @@ -112,7 +112,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04-base", nil) - mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) + mockPackageManager.EXPECT().GetBaseimagePath("", false, false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) mockFileIO.EXPECT().Create("Dockerfile").Return(tempFile, nil) mockImageManager.EXPECT().LoadImage("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar").Return(errors.New("load failed")) @@ -148,7 +148,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04-base", nil) - mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) + mockPackageManager.EXPECT().GetBaseimagePath("", false, false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) mockFileIO.EXPECT().Create("Dockerfile").Return(tempFile, nil) mockImageManager.EXPECT().LoadImage("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar").Return(nil) diff --git a/cli/cmd/k0s/download_k0s.go b/cli/cmd/k0s/download_k0s.go index cff80a7fd..0d291de9b 100644 --- a/cli/cmd/k0s/download_k0s.go +++ b/cli/cmd/k0s/download_k0s.go @@ -29,7 +29,6 @@ type DownloadK0sOpts struct { *util.GlobalOptions Version string Force bool - Quiet bool } func (c *DownloadK0sCmd) RunE(_ *cobra.Command, args []string) error { @@ -55,7 +54,6 @@ func AddDownloadCmd(download *cobra.Command, opts *util.GlobalOptions) { Example: util.FormatExamples("download k0s", []packageio.Example{ {Cmd: "", Desc: "Download k0s using the Go-native implementation"}, {Cmd: "--version 1.22.0", Desc: "Download a specific version of k0s"}, - {Cmd: "--quiet", Desc: "Download k0s with minimal output"}, {Cmd: "--force", Desc: "Force download even if k0s binary exists"}, }), }, @@ -65,7 +63,6 @@ func AddDownloadCmd(download *cobra.Command, opts *util.GlobalOptions) { } k0s.cmd.Flags().StringVarP(&k0s.Opts.Version, "version", "v", "", "Version of k0s to download") k0s.cmd.Flags().BoolVarP(&k0s.Opts.Force, "force", "f", false, "Force download even if k0s binary exists") - k0s.cmd.Flags().BoolVarP(&k0s.Opts.Quiet, "quiet", "q", false, "Suppress progress output during download") util.AddCmd(download, k0s.cmd) @@ -82,7 +79,7 @@ func (c *DownloadK0sCmd) DownloadK0s(k0s installer.K0sManager) error { } } - k0sPath, err := k0s.Download(version, c.Opts.Force, c.Opts.Quiet) + k0sPath, err := k0s.Download(version, c.Opts.Force, !c.Opts.Verbose) if err != nil { return fmt.Errorf("failed to download k0s: %w", err) } diff --git a/cli/cmd/k0s/download_k0s_test.go b/cli/cmd/k0s/download_k0s_test.go index bdb3fc4a0..266900b82 100644 --- a/cli/cmd/k0s/download_k0s_test.go +++ b/cli/cmd/k0s/download_k0s_test.go @@ -33,7 +33,6 @@ var _ = Describe("DownloadK0sk0s", func() { GlobalOptions: globalOpts, Version: "", Force: false, - Quiet: false, } c = k0s.DownloadK0sCmd{ Opts: *opts, @@ -64,7 +63,7 @@ var _ = Describe("DownloadK0sk0s", func() { mockK0sManager := installer.NewMockK0sManager(GinkgoT()) c.Opts.Version = "v1.29.1+k0s.0" - mockK0sManager.EXPECT().Download("v1.29.1+k0s.0", false, false).Return("", errors.New("download failed")) + mockK0sManager.EXPECT().Download("v1.29.1+k0s.0", false, true).Return("", errors.New("download failed")) err := c.DownloadK0s(mockK0sManager) Expect(err).To(HaveOccurred()) @@ -76,7 +75,7 @@ var _ = Describe("DownloadK0sk0s", func() { mockK0sManager := installer.NewMockK0sManager(GinkgoT()) c.Opts.Version = "v1.29.1+k0s.0" - mockK0sManager.EXPECT().Download("v1.29.1+k0s.0", false, false).Return("/test/workdir/k0s", nil) + mockK0sManager.EXPECT().Download("v1.29.1+k0s.0", false, true).Return("/test/workdir/k0s", nil) err := c.DownloadK0s(mockK0sManager) Expect(err).ToNot(HaveOccurred()) @@ -87,9 +86,9 @@ var _ = Describe("DownloadK0sk0s", func() { c.Opts.Version = "" // Test auto-version detection c.Opts.Force = true - c.Opts.Quiet = true + c.Opts.Verbose = true mockK0sManager.EXPECT().GetLatestVersion().Return("v1.29.1+k0s.0", nil) - mockK0sManager.EXPECT().Download("v1.29.1+k0s.0", true, true).Return("/test/workdir/k0s", nil) + mockK0sManager.EXPECT().Download("v1.29.1+k0s.0", true, false).Return("/test/workdir/k0s", nil) err := c.DownloadK0s(mockK0sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/cli/cmd/update_dockerfile.go b/cli/cmd/update_dockerfile.go index fe3325780..be72c95ea 100644 --- a/cli/cmd/update_dockerfile.go +++ b/cli/cmd/update_dockerfile.go @@ -92,7 +92,7 @@ func (c *UpdateDockerfileCmd) UpdateDockerfile(pm installer.PackageManager, im s return fmt.Errorf("failed to get image name: %w", err) } - imagePath, err := pm.GetBaseimagePath(c.Opts.Baseimage, c.Opts.Force) + imagePath, err := pm.GetBaseimagePath(c.Opts.Baseimage, c.Opts.Force, c.Opts.Verbose) if err != nil { return fmt.Errorf("failed to get image path: %w", err) } diff --git a/cli/cmd/update_dockerfile_test.go b/cli/cmd/update_dockerfile_test.go index ca6c9ee2a..4f4d1a5f7 100644 --- a/cli/cmd/update_dockerfile_test.go +++ b/cli/cmd/update_dockerfile_test.go @@ -107,7 +107,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04", nil) - mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) + mockPackageManager.EXPECT().GetBaseimagePath("", false, false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockImageManager.EXPECT().LoadImage("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar").Return(nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) mockFileIO.EXPECT().Open("Dockerfile").Return(nil, errors.New("file not found")) @@ -127,7 +127,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04", nil) - mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) + mockPackageManager.EXPECT().GetBaseimagePath("", false, false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockImageManager.EXPECT().LoadImage("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar").Return(errors.New("load failed")) err := c.UpdateDockerfile(mockPackageManager, mockImageManager, []string{}) @@ -158,7 +158,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04", nil) - mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) + mockPackageManager.EXPECT().GetBaseimagePath("", false, false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockImageManager.EXPECT().LoadImage("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar").Return(nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) mockFileIO.EXPECT().Open("Dockerfile").Return(tempFile, nil) @@ -192,7 +192,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("ubuntu:24.04", nil) - mockPackageManager.EXPECT().GetBaseimagePath("", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) + mockPackageManager.EXPECT().GetBaseimagePath("", false, false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) mockFileIO.EXPECT().Open("Dockerfile").Return(tempFile, nil) mockFileIO.EXPECT().WriteFile("Dockerfile", []byte("FROM ubuntu:24.04\nRUN apt-get update && apt-get install -y curl\nWORKDIR /app\nCOPY . .\nCMD [\"./start.sh\"]"), os.FileMode(0644)).Return(nil) @@ -225,7 +225,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { mockPackageManager.EXPECT().Extract(true, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("workspace-agent-20.04.tar").Return("ubuntu:20.04", nil) - mockPackageManager.EXPECT().GetBaseimagePath("workspace-agent-20.04.tar", true).Return("/test/workdir/deps/codesphere/images/workspace-agent-20.04.tar", nil) + mockPackageManager.EXPECT().GetBaseimagePath("workspace-agent-20.04.tar", true, false).Return("/test/workdir/deps/codesphere/images/workspace-agent-20.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) mockFileIO.EXPECT().Open("Dockerfile").Return(tempFile, nil) mockFileIO.EXPECT().WriteFile("Dockerfile", []byte("FROM ubuntu:20.04\nRUN apt-get update && apt-get install -y curl\nWORKDIR /app\nCOPY . .\nCMD [\"./start.sh\"]"), os.FileMode(0644)).Return(nil) @@ -258,7 +258,7 @@ var _ = Describe("UpdateDockerfileCmd", func() { mockPackageManager.EXPECT().Extract(false, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("workspace-agent-24.04.tar").Return("registry.example.com/workspace-agent:24.04", nil) - mockPackageManager.EXPECT().GetBaseimagePath("workspace-agent-24.04.tar", false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) + mockPackageManager.EXPECT().GetBaseimagePath("workspace-agent-24.04.tar", false, false).Return("/test/workdir/deps/codesphere/images/workspace-agent-24.04.tar", nil) mockPackageManager.EXPECT().FileIO().Return(mockFileIO) mockFileIO.EXPECT().Open("custom/Dockerfile").Return(tempFile, nil) mockFileIO.EXPECT().WriteFile("custom/Dockerfile", []byte("FROM registry.example.com/workspace-agent:24.04\nRUN apt-get update && apt-get install -y curl\nWORKDIR /app\nCOPY . .\nCMD [\"./start.sh\"]"), os.FileMode(0644)).Return(nil) diff --git a/docs/oms_download_k0s.md b/docs/oms_download_k0s.md index 9e74e770e..64e381303 100644 --- a/docs/oms_download_k0s.md +++ b/docs/oms_download_k0s.md @@ -20,9 +20,6 @@ $ oms download k0s # Download a specific version of k0s $ oms download k0s --version 1.22.0 -# Download k0s with minimal output -$ oms download k0s --quiet - # Force download even if k0s binary exists $ oms download k0s --force @@ -33,7 +30,6 @@ $ oms download k0s --force ``` -f, --force Force download even if k0s binary exists -h, --help help for k0s - -q, --quiet Suppress progress output during download -v, --version string Version of k0s to download ``` diff --git a/docs/oms_download_package.md b/docs/oms_download_package.md index 99b2b3b1b..a5e50f390 100644 --- a/docs/oms_download_package.md +++ b/docs/oms_download_package.md @@ -31,7 +31,6 @@ $ oms download package --version codesphere-v1.55.0 --file installer-lite.tar.gz -f, --file string Specify artifact to download (default "installer-lite.tar.gz") -H, --hash string Hash of the version to download if multiple builds exist for the same version -h, --help help for package - -q, --quiet Suppress progress output during download -V, --version string Codesphere version to download ``` diff --git a/docs/oms_smoketest_codesphere.md b/docs/oms_smoketest_codesphere.md index 64cb17523..929532ccd 100644 --- a/docs/oms_smoketest_codesphere.md +++ b/docs/oms_smoketest_codesphere.md @@ -24,9 +24,6 @@ $ oms smoketest codesphere --baseurl https://codesphere.example.com/api --token # Run smoke tests against a specific team within your Codesphere installation, using a specific workspace plan $ oms smoketest codesphere --baseurl https://codesphere.example.com/api --token YOUR_TOKEN --team-id TEAM_ID --plan-id PLAN_ID -# Run smoke tests in quiet mode (no progress logging) -$ oms smoketest codesphere --baseurl https://codesphere.example.com/api --token YOUR_TOKEN --quiet - # Run smoke tests with custom timeout $ oms smoketest codesphere --baseurl https://codesphere.example.com/api --token YOUR_TOKEN --timeout 15m @@ -45,7 +42,6 @@ $ oms smoketest codesphere --baseurl https://codesphere.example.com/api --token -h, --help help for codesphere --plan-id string Plan ID for workspace creation --profile string CI profile to use for landscape and pipeline (default "ci.yml") - -q, --quiet Suppress progress logging --steps strings Comma-separated list of steps to run (createWorkspace,setEnvVar,createFiles,syncLandscape,executeRunStage,deleteWorkspace). If empty, all steps including deleteWorkspace are run. If specified without deleteWorkspace, the workspace will be kept for manual inspection. --team-id string Team ID for workspace creation --timeout duration Timeout for the entire smoke test (default 10m0s) diff --git a/internal/bootstrap/local/installer.go b/internal/bootstrap/local/installer.go index 957443538..8600f5d2f 100644 --- a/internal/bootstrap/local/installer.go +++ b/internal/bootstrap/local/installer.go @@ -156,7 +156,7 @@ func (b *LocalBootstrapper) PrepareInstallerBundle() (string, error) { } log.Printf("Extracting installer bundle %s → %s", bundlePath, destDir) - if err := util.ExtractTarGz(b.fw, bundlePath, destDir, false); err != nil { + if err := util.ExtractTarGz(b.fw, bundlePath, destDir, b.Verbose); err != nil { return "", fmt.Errorf("failed to extract installer bundle: %w", err) } @@ -423,7 +423,7 @@ func (b *LocalBootstrapper) RunInstaller() (err error) { log.Printf("deps directory already exists at %s, skipping extraction", depsDir) } else { log.Printf("Extracting deps.tar.gz → %s", depsDir) - if err := util.ExtractTarGz(b.fw, archivePath, depsDir, false); err != nil { + if err := util.ExtractTarGz(b.fw, archivePath, depsDir, b.Verbose); err != nil { return fmt.Errorf("failed to extract deps.tar.gz: %w", err) } } diff --git a/internal/bootstrap/local/local.go b/internal/bootstrap/local/local.go index 4dad4255a..f93fb49dd 100644 --- a/internal/bootstrap/local/local.go +++ b/internal/bootstrap/local/local.go @@ -59,6 +59,7 @@ type LocalBootstrapper struct { fw util.FileIO icg installer.InstallConfigManager helm installer.HelmClient + Verbose bool // Environment Env *CodesphereEnvironment // cephCredentials holds the Ceph auth credentials read after setup. @@ -99,7 +100,7 @@ type CodesphereEnvironment struct { ArgoCDRegistryURL string `json:"-"` } -func NewLocalBootstrapper(ctx context.Context, stlog *bootstrap.StepLogger, kubeClient client.Client, restConfig *rest.Config, fw util.FileIO, icg installer.InstallConfigManager, helm installer.HelmClient, env *CodesphereEnvironment) *LocalBootstrapper { +func NewLocalBootstrapper(ctx context.Context, stlog *bootstrap.StepLogger, kubeClient client.Client, restConfig *rest.Config, fw util.FileIO, icg installer.InstallConfigManager, helm installer.HelmClient, env *CodesphereEnvironment, verbose bool) *LocalBootstrapper { return &LocalBootstrapper{ ctx: ctx, stlog: stlog, @@ -109,6 +110,7 @@ func NewLocalBootstrapper(ctx context.Context, stlog *bootstrap.StepLogger, kube icg: icg, helm: helm, Env: env, + Verbose: verbose, } } diff --git a/internal/codesphere/teststeps/step.go b/internal/codesphere/teststeps/step.go index 593730e47..93b1d5447 100644 --- a/internal/codesphere/teststeps/step.go +++ b/internal/codesphere/teststeps/step.go @@ -30,7 +30,7 @@ type SmoketestCodesphereOpts struct { Token string TeamID string PlanID string - Quiet bool + Verbose bool Timeout time.Duration Profile string Steps []string @@ -39,19 +39,19 @@ type SmoketestCodesphereOpts struct { // Logging helpers func (c *SmoketestCodesphereOpts) logStep(message string) { - if !c.Quiet { + if c.Verbose { fmt.Printf("%s...", message) } } func (c *SmoketestCodesphereOpts) logSuccess() { - if !c.Quiet { + if c.Verbose { fmt.Printf(" %ssucceeded%s\n", colorGreen, colorReset) } } func (c *SmoketestCodesphereOpts) logFailure() { - if !c.Quiet { + if c.Verbose { fmt.Printf(" %sfailed%s\n", colorRed, colorReset) } } diff --git a/internal/installer/codesphere.go b/internal/installer/codesphere.go index 79efc87bc..e5fa72922 100644 --- a/internal/installer/codesphere.go +++ b/internal/installer/codesphere.go @@ -67,6 +67,8 @@ type CodesphereInstaller struct { PrivKey string // Force re-extracts the package even if the work directory already exists. Force bool + // Verbose enables detailed package extraction output. + Verbose bool // SkipSteps lists installer steps to skip within the active step set. SkipSteps []string // AllowedSteps restricts execution to a subset of KnownInstallerSteps. @@ -179,7 +181,7 @@ func (ci *CodesphereInstaller) warnIfVaultDirDiffersFromSecretsDir(config files. } func (ci *CodesphereInstaller) ExtractAndValidatePackage(pm PackageManager) error { - if err := pm.Extract(ci.Force, false); err != nil { + if err := pm.Extract(ci.Force, ci.Verbose); err != nil { return fmt.Errorf("failed to extract package to workdir: %w", err) } @@ -198,7 +200,7 @@ func (ci *CodesphereInstaller) ExtractAndValidatePackage(pm PackageManager) erro return fmt.Errorf("node executable not found in package") } - if err := pm.ExtractDependency("bom.json", ci.Force, false); err != nil { + if err := pm.ExtractDependency("bom.json", ci.Force, ci.Verbose); err != nil { return fmt.Errorf("failed to extract package to workdir: %w", err) } @@ -309,7 +311,7 @@ func splitImageTag(fullImageTag string) (string, string, error) { func (ci *CodesphereInstaller) extractAndLoadRootImage(pm PackageManager, im system.ImageManager, rootImageName, dockerfile string) error { imagePath := filepath.Join("codesphere", "images", fmt.Sprintf("%s.tar", rootImageName)) - if err := pm.ExtractDependency(imagePath, ci.Force, false); err != nil { + if err := pm.ExtractDependency(imagePath, ci.Force, ci.Verbose); err != nil { return fmt.Errorf("failed to extract root image %s: %w", imagePath, err) } diff --git a/internal/installer/codesphere_test.go b/internal/installer/codesphere_test.go index 9828d9d3d..6cf4df9e6 100644 --- a/internal/installer/codesphere_test.go +++ b/internal/installer/codesphere_test.go @@ -4,13 +4,40 @@ package installer_test import ( + "os" + "path/filepath" + "github.com/codesphere-cloud/oms/internal/installer" "github.com/codesphere-cloud/oms/internal/installer/files" + "github.com/codesphere-cloud/oms/internal/util" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) var _ = Describe("Codesphere installer", func() { + It("passes verbose output through package extraction", func() { + packageDir := GinkgoT().TempDir() + for _, name := range []string{"deps.tar.gz", "private-cloud-installer.js", "node"} { + Expect(os.WriteFile(filepath.Join(packageDir, name), nil, 0600)).To(Succeed()) + } + entries, err := os.ReadDir(packageDir) + Expect(err).NotTo(HaveOccurred()) + + fileIO := util.NewMockFileIO(GinkgoT()) + fileIO.EXPECT().Exists(packageDir).Return(true) + fileIO.EXPECT().ReadDir(packageDir).Return(entries, nil) + packageManager := installer.NewMockPackageManager(GinkgoT()) + packageManager.EXPECT().Extract(false, true).Return(nil) + packageManager.EXPECT().GetWorkDir().Return(packageDir) + packageManager.EXPECT().FileIO().Return(fileIO).Twice() + packageManager.EXPECT().ExtractDependency("bom.json", false, true).Return(nil) + ci := &installer.CodesphereInstaller{Verbose: true} + + err = ci.ExtractAndValidatePackage(packageManager) + + Expect(err).NotTo(HaveOccurred()) + }) + It("rejects serverAddress in postgres install mode before running PCInstaller", func() { config := files.RootConfig{ Postgres: files.PostgresConfig{ diff --git a/internal/installer/mocks.go b/internal/installer/mocks.go index c79ff0cc8..c22f4b9d7 100644 --- a/internal/installer/mocks.go +++ b/internal/installer/mocks.go @@ -1875,8 +1875,8 @@ func (_c *MockPackageManager_ExtractDependency_Call) RunAndReturn(run func(file } // ExtractOciImageIndex provides a mock function for the type MockPackageManager -func (_mock *MockPackageManager) ExtractOciImageIndex(imagefile string) (files.OCIImageIndex, error) { - ret := _mock.Called(imagefile) +func (_mock *MockPackageManager) ExtractOciImageIndex(imagefile string, verbose bool) (files.OCIImageIndex, error) { + ret := _mock.Called(imagefile, verbose) if len(ret) == 0 { panic("no return value specified for ExtractOciImageIndex") @@ -1884,16 +1884,16 @@ func (_mock *MockPackageManager) ExtractOciImageIndex(imagefile string) (files.O var r0 files.OCIImageIndex var r1 error - if returnFunc, ok := ret.Get(0).(func(string) (files.OCIImageIndex, error)); ok { - return returnFunc(imagefile) + if returnFunc, ok := ret.Get(0).(func(string, bool) (files.OCIImageIndex, error)); ok { + return returnFunc(imagefile, verbose) } - if returnFunc, ok := ret.Get(0).(func(string) files.OCIImageIndex); ok { - r0 = returnFunc(imagefile) + if returnFunc, ok := ret.Get(0).(func(string, bool) files.OCIImageIndex); ok { + r0 = returnFunc(imagefile, verbose) } else { r0 = ret.Get(0).(files.OCIImageIndex) } - if returnFunc, ok := ret.Get(1).(func(string) error); ok { - r1 = returnFunc(imagefile) + if returnFunc, ok := ret.Get(1).(func(string, bool) error); ok { + r1 = returnFunc(imagefile, verbose) } else { r1 = ret.Error(1) } @@ -1907,18 +1907,24 @@ type MockPackageManager_ExtractOciImageIndex_Call struct { // ExtractOciImageIndex is a helper method to define mock.On call // - imagefile string -func (_e *MockPackageManager_Expecter) ExtractOciImageIndex(imagefile any) *MockPackageManager_ExtractOciImageIndex_Call { - return &MockPackageManager_ExtractOciImageIndex_Call{Call: _e.mock.On("ExtractOciImageIndex", imagefile)} +// - verbose bool +func (_e *MockPackageManager_Expecter) ExtractOciImageIndex(imagefile any, verbose any) *MockPackageManager_ExtractOciImageIndex_Call { + return &MockPackageManager_ExtractOciImageIndex_Call{Call: _e.mock.On("ExtractOciImageIndex", imagefile, verbose)} } -func (_c *MockPackageManager_ExtractOciImageIndex_Call) Run(run func(imagefile string)) *MockPackageManager_ExtractOciImageIndex_Call { +func (_c *MockPackageManager_ExtractOciImageIndex_Call) Run(run func(imagefile string, verbose bool)) *MockPackageManager_ExtractOciImageIndex_Call { _c.Call.Run(func(args mock.Arguments) { var arg0 string if args[0] != nil { arg0 = args[0].(string) } + var arg1 bool + if args[1] != nil { + arg1 = args[1].(bool) + } run( arg0, + arg1, ) }) return _c @@ -1929,7 +1935,7 @@ func (_c *MockPackageManager_ExtractOciImageIndex_Call) Return(oCIImageIndex fil return _c } -func (_c *MockPackageManager_ExtractOciImageIndex_Call) RunAndReturn(run func(imagefile string) (files.OCIImageIndex, error)) *MockPackageManager_ExtractOciImageIndex_Call { +func (_c *MockPackageManager_ExtractOciImageIndex_Call) RunAndReturn(run func(imagefile string, verbose bool) (files.OCIImageIndex, error)) *MockPackageManager_ExtractOciImageIndex_Call { _c.Call.Return(run) return _c } @@ -1981,8 +1987,8 @@ func (_c *MockPackageManager_FileIO_Call) RunAndReturn(run func() util.FileIO) * } // GetBaseimagePath provides a mock function for the type MockPackageManager -func (_mock *MockPackageManager) GetBaseimagePath(baseimage string, force bool) (string, error) { - ret := _mock.Called(baseimage, force) +func (_mock *MockPackageManager) GetBaseimagePath(baseimage string, force bool, verbose bool) (string, error) { + ret := _mock.Called(baseimage, force, verbose) if len(ret) == 0 { panic("no return value specified for GetBaseimagePath") @@ -1990,16 +1996,16 @@ func (_mock *MockPackageManager) GetBaseimagePath(baseimage string, force bool) var r0 string var r1 error - if returnFunc, ok := ret.Get(0).(func(string, bool) (string, error)); ok { - return returnFunc(baseimage, force) + if returnFunc, ok := ret.Get(0).(func(string, bool, bool) (string, error)); ok { + return returnFunc(baseimage, force, verbose) } - if returnFunc, ok := ret.Get(0).(func(string, bool) string); ok { - r0 = returnFunc(baseimage, force) + if returnFunc, ok := ret.Get(0).(func(string, bool, bool) string); ok { + r0 = returnFunc(baseimage, force, verbose) } else { r0 = ret.Get(0).(string) } - if returnFunc, ok := ret.Get(1).(func(string, bool) error); ok { - r1 = returnFunc(baseimage, force) + if returnFunc, ok := ret.Get(1).(func(string, bool, bool) error); ok { + r1 = returnFunc(baseimage, force, verbose) } else { r1 = ret.Error(1) } @@ -2014,11 +2020,12 @@ type MockPackageManager_GetBaseimagePath_Call struct { // GetBaseimagePath is a helper method to define mock.On call // - baseimage string // - force bool -func (_e *MockPackageManager_Expecter) GetBaseimagePath(baseimage any, force any) *MockPackageManager_GetBaseimagePath_Call { - return &MockPackageManager_GetBaseimagePath_Call{Call: _e.mock.On("GetBaseimagePath", baseimage, force)} +// - verbose bool +func (_e *MockPackageManager_Expecter) GetBaseimagePath(baseimage any, force any, verbose any) *MockPackageManager_GetBaseimagePath_Call { + return &MockPackageManager_GetBaseimagePath_Call{Call: _e.mock.On("GetBaseimagePath", baseimage, force, verbose)} } -func (_c *MockPackageManager_GetBaseimagePath_Call) Run(run func(baseimage string, force bool)) *MockPackageManager_GetBaseimagePath_Call { +func (_c *MockPackageManager_GetBaseimagePath_Call) Run(run func(baseimage string, force bool, verbose bool)) *MockPackageManager_GetBaseimagePath_Call { _c.Call.Run(func(args mock.Arguments) { var arg0 string if args[0] != nil { @@ -2028,9 +2035,14 @@ func (_c *MockPackageManager_GetBaseimagePath_Call) Run(run func(baseimage strin if args[1] != nil { arg1 = args[1].(bool) } + var arg2 bool + if args[2] != nil { + arg2 = args[2].(bool) + } run( arg0, arg1, + arg2, ) }) return _c @@ -2041,7 +2053,7 @@ func (_c *MockPackageManager_GetBaseimagePath_Call) Return(s string, err error) return _c } -func (_c *MockPackageManager_GetBaseimagePath_Call) RunAndReturn(run func(baseimage string, force bool) (string, error)) *MockPackageManager_GetBaseimagePath_Call { +func (_c *MockPackageManager_GetBaseimagePath_Call) RunAndReturn(run func(baseimage string, force bool, verbose bool) (string, error)) *MockPackageManager_GetBaseimagePath_Call { _c.Call.Return(run) return _c } diff --git a/internal/installer/package.go b/internal/installer/package.go index 5d4e7d719..7cdfd083d 100644 --- a/internal/installer/package.go +++ b/internal/installer/package.go @@ -26,9 +26,9 @@ type PackageManager interface { GetDependencyPath(filename string) string Extract(force bool, verbose bool) error ExtractDependency(file string, force bool, verbose bool) error - ExtractOciImageIndex(imagefile string) (files.OCIImageIndex, error) + ExtractOciImageIndex(imagefile string, verbose bool) (files.OCIImageIndex, error) GetFullImageTag(baseimage string) (string, error) - GetBaseimagePath(baseimage string, force bool) (string, error) + GetBaseimagePath(baseimage string, force bool, verbose bool) (string, error) GetCodesphereVersion() (string, error) } @@ -133,9 +133,9 @@ func (p *Package) ExtractDependency(file string, force bool, verbose bool) error } // ExtractOciImageIndex extracts and parses the OCI image index from the given image file path. -func (p *Package) ExtractOciImageIndex(imagefile string) (files.OCIImageIndex, error) { +func (p *Package) ExtractOciImageIndex(imagefile string, verbose bool) (files.OCIImageIndex, error) { var ociImageIndex files.OCIImageIndex - err := util.ExtractTarSingleFile(p.fileIO, imagefile, "index.json", filepath.Dir(imagefile), false) + err := util.ExtractTarSingleFile(p.fileIO, imagefile, "index.json", filepath.Dir(imagefile), verbose) if err != nil { return ociImageIndex, fmt.Errorf("failed to extract index.json: %w", err) } @@ -173,7 +173,7 @@ func (p *Package) GetFullImageTag(baseimage string) (string, error) { const baseimagePath = "./codesphere/images" -func (p *Package) GetBaseimagePath(baseimage string, force bool) (string, error) { +func (p *Package) GetBaseimagePath(baseimage string, force bool, verbose bool) (string, error) { if baseimage == "" { return "", fmt.Errorf("baseimage not specified") } @@ -183,7 +183,7 @@ func (p *Package) GetBaseimagePath(baseimage string, force bool) (string, error) } baseImageTarPath := path.Join(baseimagePath, baseimage) - err := p.ExtractDependency(baseImageTarPath, force, false) + err := p.ExtractDependency(baseImageTarPath, force, verbose) if err != nil { return "", fmt.Errorf("failed to extract package to workdir: %w", err) } diff --git a/internal/installer/package_test.go b/internal/installer/package_test.go index c8a8880fb..a0937234b 100644 --- a/internal/installer/package_test.go +++ b/internal/installer/package_test.go @@ -250,7 +250,7 @@ var _ = Describe("Package ExtractOciImageIndex", func() { Context("when image file does not exist", func() { It("returns an error", func() { - _, err := pkg.ExtractOciImageIndex(imageFile) + _, err := pkg.ExtractOciImageIndex(imageFile, false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("failed to extract index.json")) @@ -263,7 +263,7 @@ var _ = Describe("Package ExtractOciImageIndex", func() { err := os.WriteFile(imageFile, []byte(""), 0644) Expect(err).ToNot(HaveOccurred()) - _, err = pkg.ExtractOciImageIndex(imageFile) + _, err = pkg.ExtractOciImageIndex(imageFile, false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("failed to extract index.json")) }) @@ -275,7 +275,7 @@ var _ = Describe("Package ExtractOciImageIndex", func() { err := os.Mkdir(imageFile, 0755) Expect(err).ToNot(HaveOccurred()) - _, err = pkg.ExtractOciImageIndex(imageFile) + _, err = pkg.ExtractOciImageIndex(imageFile, false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("failed to extract index.json")) }) @@ -287,7 +287,7 @@ var _ = Describe("Package ExtractOciImageIndex", func() { err := createTar(imageFile, "not_index.json", "fake content") Expect(err).ToNot(HaveOccurred()) - _, err = pkg.ExtractOciImageIndex(imageFile) + _, err = pkg.ExtractOciImageIndex(imageFile, false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("failed to extract index.json")) }) @@ -310,7 +310,7 @@ var _ = Describe("Package ExtractOciImageIndex", func() { err := createTar(imageFile, "index.json", validIndex) Expect(err).ToNot(HaveOccurred()) - ociImageIndex, err := pkg.ExtractOciImageIndex(imageFile) + ociImageIndex, err := pkg.ExtractOciImageIndex(imageFile, false) Expect(err).ToNot(HaveOccurred()) Expect(ociImageIndex.SchemaVersion).To(Equal(2)) Expect(ociImageIndex.MediaType).To(Equal("application/vnd.oci.image.index.v1+json")) @@ -332,7 +332,7 @@ var _ = Describe("Package ExtractOciImageIndex", func() { err := createTar(imageFile, "index.json", invalidIndex) Expect(err).ToNot(HaveOccurred()) - _, err = pkg.ExtractOciImageIndex(imageFile) + _, err = pkg.ExtractOciImageIndex(imageFile, false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("failed to parse OCI image config")) }) @@ -491,7 +491,7 @@ var _ = Describe("Package GetBaseimagePath", func() { Describe("GetBaseimagePath", func() { Context("when baseimage parameter is empty", func() { It("returns an error", func() { - _, err := pkg.GetBaseimagePath("", false) + _, err := pkg.GetBaseimagePath("", false, false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("baseimage not specified")) }) @@ -500,7 +500,7 @@ var _ = Describe("Package GetBaseimagePath", func() { Context("when ExtractDependency fails", func() { It("returns an error", func() { // Try to extract non-existent dependency - _, err := pkg.GetBaseimagePath("nonexistent-image", false) + _, err := pkg.GetBaseimagePath("nonexistent-image", false, false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("failed to extract package to workdir")) }) @@ -523,7 +523,7 @@ var _ = Describe("Package GetBaseimagePath", func() { }) It("returns correct path for baseimage without .tar extension", func() { - path, err := pkg.GetBaseimagePath("workspace-agent-24.04", false) + path, err := pkg.GetBaseimagePath("workspace-agent-24.04", false, false) Expect(err).NotTo(HaveOccurred()) expectedPath := pkg.GetDependencyPath("./codesphere/images/workspace-agent-24.04.tar") @@ -531,7 +531,7 @@ var _ = Describe("Package GetBaseimagePath", func() { }) It("returns correct path for baseimage with .tar extension", func() { - path, err := pkg.GetBaseimagePath("workspace-agent-24.04.tar", false) + path, err := pkg.GetBaseimagePath("workspace-agent-24.04.tar", false, false) Expect(err).NotTo(HaveOccurred()) expectedPath := pkg.GetDependencyPath("./codesphere/images/workspace-agent-24.04.tar") @@ -540,11 +540,11 @@ var _ = Describe("Package GetBaseimagePath", func() { It("uses force parameter correctly", func() { // First extraction - _, err := pkg.GetBaseimagePath("workspace-agent-24.04", false) + _, err := pkg.GetBaseimagePath("workspace-agent-24.04", false, false) Expect(err).NotTo(HaveOccurred()) // Second extraction with force - path, err := pkg.GetBaseimagePath("workspace-agent-24.04", true) + path, err := pkg.GetBaseimagePath("workspace-agent-24.04", true, false) Expect(err).NotTo(HaveOccurred()) expectedPath := pkg.GetDependencyPath("./codesphere/images/workspace-agent-24.04.tar") diff --git a/internal/util/tar.go b/internal/util/tar.go index 9d0d1d198..ccd436690 100644 --- a/internal/util/tar.go +++ b/internal/util/tar.go @@ -9,7 +9,6 @@ import ( "compress/gzip" "fmt" "io" - "log" "os" "path/filepath" "strings" @@ -37,8 +36,8 @@ func getCleanTargetPath(destDir string, header *tar.Header) (string, error) { } // openTar opens a .tar file and returns a tar.Reader to read its contents. -func openTar(filename string, fileIo FileIO) (*tar.Reader, error) { - log.Printf("Opening archive: %s", filename) +func openTar(filename string, fileIo FileIO, verbose bool) (*tar.Reader, error) { + csio.Verbosef(verbose, "Opening archive: %s", filename) file, err := fileIo.Open(filename) if err != nil { return nil, fmt.Errorf("failed to open archive: %w", err) @@ -50,8 +49,8 @@ func openTar(filename string, fileIo FileIO) (*tar.Reader, error) { } // openTarGz opens a .tar.gz file and returns a tar.Reader to read its contents. -func openTarGz(filename string, fileIo FileIO) (*tar.Reader, error) { - log.Printf("Opening archive: %s", filename) +func openTarGz(filename string, fileIo FileIO, verbose bool) (*tar.Reader, error) { + csio.Verbosef(verbose, "Opening archive: %s", filename) file, err := fileIo.Open(filename) if err != nil { return nil, fmt.Errorf("failed to open archive: %w", err) @@ -68,7 +67,7 @@ func openTarGz(filename string, fileIo FileIO) (*tar.Reader, error) { } // extractEntry extracts a single tar.Header entry to the targetPath using the provided tar.Reader. -func extractEntry(header *tar.Header, targetPath string, fileIo FileIO, tr *tar.Reader) error { +func extractEntry(header *tar.Header, targetPath string, fileIo FileIO, tr *tar.Reader, verbose bool) error { switch header.Typeflag { case tar.TypeDir: if err := fileIo.MkdirAll(targetPath, os.FileMode(header.Mode)); err != nil { @@ -101,7 +100,7 @@ func extractEntry(header *tar.Header, targetPath string, fileIo FileIO, tr *tar. } default: - log.Printf("Ignoring unsupported header type flag %c for %s", header.Typeflag, header.Name) + csio.Verbosef(verbose, "Ignoring unsupported header type flag %c for %s", header.Typeflag, header.Name) } return nil } @@ -109,7 +108,7 @@ func extractEntry(header *tar.Header, targetPath string, fileIo FileIO, tr *tar. // ExtractTarGzSingleFile extracts a single specified file from a .tar.gz archive to the destination directory. func ExtractTarGzSingleFile(fileIo FileIO, archiveFile, fileToExtract, destDir string, verbose bool) error { destDir = filepath.Clean(destDir) - tr, err := openTarGz(archiveFile, fileIo) + tr, err := openTarGz(archiveFile, fileIo, verbose) if err != nil { return err } @@ -119,7 +118,7 @@ func ExtractTarGzSingleFile(fileIo FileIO, archiveFile, fileToExtract, destDir s // ExtractTarSingleFile extracts a single specified file from a .tar archive to the destination directory. func ExtractTarSingleFile(fileIo FileIO, archiveFile, fileToExtract, destDir string, verbose bool) error { destDir = filepath.Clean(destDir) - tr, err := openTar(archiveFile, fileIo) + tr, err := openTar(archiveFile, fileIo, verbose) if err != nil { return err } @@ -151,7 +150,7 @@ func extractTarSingleFile(fileIo FileIO, tr *tar.Reader, fileToExtract, destDir return err } - err = extractEntry(header, targetPath, fileIo, tr) + err = extractEntry(header, targetPath, fileIo, tr, verbose) if err != nil { return err } diff --git a/internal/util/tar_test.go b/internal/util/tar_test.go index 2a4b7078c..181bc0832 100644 --- a/internal/util/tar_test.go +++ b/internal/util/tar_test.go @@ -8,6 +8,9 @@ import ( "bytes" "compress/gzip" "io" + "log" + "os" + "path/filepath" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -24,7 +27,8 @@ var fileContents = map[string]string{ } var _ = Describe("Tar", func() { var ( - archiveIn io.Reader + archiveIn io.Reader + archiveData []byte ) BeforeEach(func() { // Create an in-memory tar.gz containing the embedded files. @@ -53,7 +57,8 @@ var _ = Describe("Tar", func() { Expect(tw.Close()).To(Succeed()) Expect(gz.Close()).To(Succeed()) - archiveIn = bytes.NewReader(buf.Bytes()) + archiveData = append([]byte(nil), buf.Bytes()...) + archiveIn = bytes.NewReader(archiveData) }) Describe("StreamFileFromGzip", func() { @@ -79,4 +84,39 @@ var _ = Describe("Tar", func() { Expect(err).To(MatchError("file file3.txt not found in archive")) }) }) + + Describe("ExtractTarGzSingleFile", func() { + var ( + archivePath string + destination string + logOutput bytes.Buffer + ) + + BeforeEach(func() { + tempDir := GinkgoT().TempDir() + archivePath = filepath.Join(tempDir, "test.tar.gz") + destination = filepath.Join(tempDir, "extracted") + Expect(os.WriteFile(archivePath, archiveData, 0600)).To(Succeed()) + + previousLogWriter := log.Writer() + log.SetOutput(&logOutput) + DeferCleanup(func() { log.SetOutput(previousLogWriter) }) + }) + + It("does not log extraction details when verbose output is disabled", func() { + err := util.ExtractTarGzSingleFile(util.NewFilesystemWriter(), archivePath, "file1.txt", destination, false) + + Expect(err).NotTo(HaveOccurred()) + Expect(logOutput.String()).To(BeEmpty()) + }) + + It("logs extraction details when verbose output is enabled", func() { + err := util.ExtractTarGzSingleFile(util.NewFilesystemWriter(), archivePath, "file1.txt", destination, true) + + Expect(err).NotTo(HaveOccurred()) + Expect(logOutput.String()).To(ContainSubstring("Opening archive:")) + Expect(logOutput.String()).To(ContainSubstring("Extracting file1.txt from archive")) + Expect(logOutput.String()).To(ContainSubstring("File file1.txt extracted to")) + }) + }) }) From e01ccaf6e0f022183edfb192fdba8d9904b7811b Mon Sep 17 00:00:00 2001 From: NautiluX <2600004+NautiluX@users.noreply.github.com> Date: Thu, 13 Aug 2026 09:28:15 +0000 Subject: [PATCH 3/4] chore(docs): Auto-update docs and licenses Signed-off-by: NautiluX <2600004+NautiluX@users.noreply.github.com> --- NOTICE | 8 ++++---- internal/tmpl/NOTICE | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/NOTICE b/NOTICE index 356c7ff32..682ed524f 100644 --- a/NOTICE +++ b/NOTICE @@ -199,7 +199,7 @@ License URL: https://github.com/beorn7/perks/blob/v1.0.1/LICENSE Module: github.com/blang/semver/v4 Version: v4.0.0 License: MIT -License URL: https://github.com/blang/semver/blob/v4.0.0/LICENSE +License URL: https://github.com/blang/semver/blob/v4.0.0/v4/LICENSE ---------- Module: github.com/bmatcuk/doublestar/v4 @@ -385,7 +385,7 @@ License URL: https://github.com/emirpasic/gods/blob/v1.18.1/LICENSE Module: github.com/evanphx/json-patch/v5 Version: v5.9.11 License: BSD-3-Clause -License URL: https://github.com/evanphx/json-patch/blob/v5.9.11/LICENSE +License URL: https://github.com/evanphx/json-patch/blob/v5.9.11/v5/LICENSE ---------- Module: github.com/exponent-io/jsonpath @@ -709,7 +709,7 @@ License URL: https://github.com/googleapis/enterprise-certificate-proxy/blob/v0. Module: github.com/googleapis/gax-go/v2 Version: v2.23.0 License: BSD-3-Clause -License URL: https://github.com/googleapis/gax-go/blob/v2.23.0/LICENSE +License URL: https://github.com/googleapis/gax-go/blob/v2.23.0/v2/LICENSE ---------- Module: github.com/gorilla/websocket @@ -1471,7 +1471,7 @@ License URL: https://cs.opensource.google/go/x/time/+/v0.15.0:LICENSE Module: gomodules.xyz/jsonpatch/v2 Version: v2.5.0 License: Apache-2.0 -License URL: https://github.com/gomodules/jsonpatch/blob/v2.5.0/LICENSE +License URL: https://github.com/gomodules/jsonpatch/blob/v2.5.0/v2/LICENSE ---------- Module: google.golang.org/api diff --git a/internal/tmpl/NOTICE b/internal/tmpl/NOTICE index 356c7ff32..682ed524f 100644 --- a/internal/tmpl/NOTICE +++ b/internal/tmpl/NOTICE @@ -199,7 +199,7 @@ License URL: https://github.com/beorn7/perks/blob/v1.0.1/LICENSE Module: github.com/blang/semver/v4 Version: v4.0.0 License: MIT -License URL: https://github.com/blang/semver/blob/v4.0.0/LICENSE +License URL: https://github.com/blang/semver/blob/v4.0.0/v4/LICENSE ---------- Module: github.com/bmatcuk/doublestar/v4 @@ -385,7 +385,7 @@ License URL: https://github.com/emirpasic/gods/blob/v1.18.1/LICENSE Module: github.com/evanphx/json-patch/v5 Version: v5.9.11 License: BSD-3-Clause -License URL: https://github.com/evanphx/json-patch/blob/v5.9.11/LICENSE +License URL: https://github.com/evanphx/json-patch/blob/v5.9.11/v5/LICENSE ---------- Module: github.com/exponent-io/jsonpath @@ -709,7 +709,7 @@ License URL: https://github.com/googleapis/enterprise-certificate-proxy/blob/v0. Module: github.com/googleapis/gax-go/v2 Version: v2.23.0 License: BSD-3-Clause -License URL: https://github.com/googleapis/gax-go/blob/v2.23.0/LICENSE +License URL: https://github.com/googleapis/gax-go/blob/v2.23.0/v2/LICENSE ---------- Module: github.com/gorilla/websocket @@ -1471,7 +1471,7 @@ License URL: https://cs.opensource.google/go/x/time/+/v0.15.0:LICENSE Module: gomodules.xyz/jsonpatch/v2 Version: v2.5.0 License: Apache-2.0 -License URL: https://github.com/gomodules/jsonpatch/blob/v2.5.0/LICENSE +License URL: https://github.com/gomodules/jsonpatch/blob/v2.5.0/v2/LICENSE ---------- Module: google.golang.org/api From 43bee3b9311195e214a3606074c2f9940bb9ddf4 Mon Sep 17 00:00:00 2001 From: Manuel Dewald Date: Thu, 13 Aug 2026 13:40:42 +0200 Subject: [PATCH 4/4] fix: document exported verbose APIs --- cli/cmd/bootstrap_local.go | 1 + cli/cmd/extend_baseimage_test.go | 1 + cli/cmd/k0s/download_k0s_test.go | 2 ++ internal/bootstrap/local/installer.go | 2 ++ internal/bootstrap/local/local.go | 1 + internal/installer/codesphere_test.go | 3 +++ internal/installer/package.go | 4 ++++ internal/util/tar.go | 4 ++++ internal/util/tar_test.go | 2 ++ 9 files changed, 20 insertions(+) diff --git a/cli/cmd/bootstrap_local.go b/cli/cmd/bootstrap_local.go index b27bda67a..e53127e02 100644 --- a/cli/cmd/bootstrap_local.go +++ b/cli/cmd/bootstrap_local.go @@ -57,6 +57,7 @@ func (c *BootstrapLocalCmd) RunE(_ *cobra.Command, args []string) error { return nil } +// AddBootstrapLocalCmd adds the local bootstrap command to parent. func AddBootstrapLocalCmd(parent *cobra.Command, opts *util.GlobalOptions) { bootstrapLocalCmd := BootstrapLocalCmd{ cmd: &cobra.Command{ diff --git a/cli/cmd/extend_baseimage_test.go b/cli/cmd/extend_baseimage_test.go index d7e7e2ac7..f43c5e9a4 100644 --- a/cli/cmd/extend_baseimage_test.go +++ b/cli/cmd/extend_baseimage_test.go @@ -127,6 +127,7 @@ var _ = Describe("ExtendBaseimageCmd", func() { mockImageManager := system.NewMockImageManager(GinkgoT()) c.Opts.Force = true + mockPackageManager.EXPECT().Extract(true, false).Return(nil) mockPackageManager.EXPECT().GetFullImageTag("").Return("", errors.New("failed to extract package to workdir: extraction failed")) diff --git a/cli/cmd/k0s/download_k0s_test.go b/cli/cmd/k0s/download_k0s_test.go index 266900b82..33dde3222 100644 --- a/cli/cmd/k0s/download_k0s_test.go +++ b/cli/cmd/k0s/download_k0s_test.go @@ -63,6 +63,7 @@ var _ = Describe("DownloadK0sk0s", func() { mockK0sManager := installer.NewMockK0sManager(GinkgoT()) c.Opts.Version = "v1.29.1+k0s.0" + mockK0sManager.EXPECT().Download("v1.29.1+k0s.0", false, true).Return("", errors.New("download failed")) err := c.DownloadK0s(mockK0sManager) @@ -75,6 +76,7 @@ var _ = Describe("DownloadK0sk0s", func() { mockK0sManager := installer.NewMockK0sManager(GinkgoT()) c.Opts.Version = "v1.29.1+k0s.0" + mockK0sManager.EXPECT().Download("v1.29.1+k0s.0", false, true).Return("/test/workdir/k0s", nil) err := c.DownloadK0s(mockK0sManager) diff --git a/internal/bootstrap/local/installer.go b/internal/bootstrap/local/installer.go index 8600f5d2f..ab783ba76 100644 --- a/internal/bootstrap/local/installer.go +++ b/internal/bootstrap/local/installer.go @@ -156,6 +156,7 @@ func (b *LocalBootstrapper) PrepareInstallerBundle() (string, error) { } log.Printf("Extracting installer bundle %s → %s", bundlePath, destDir) + if err := util.ExtractTarGz(b.fw, bundlePath, destDir, b.Verbose); err != nil { return "", fmt.Errorf("failed to extract installer bundle: %w", err) } @@ -423,6 +424,7 @@ func (b *LocalBootstrapper) RunInstaller() (err error) { log.Printf("deps directory already exists at %s, skipping extraction", depsDir) } else { log.Printf("Extracting deps.tar.gz → %s", depsDir) + if err := util.ExtractTarGz(b.fw, archivePath, depsDir, b.Verbose); err != nil { return fmt.Errorf("failed to extract deps.tar.gz: %w", err) } diff --git a/internal/bootstrap/local/local.go b/internal/bootstrap/local/local.go index f93fb49dd..0ae3ba754 100644 --- a/internal/bootstrap/local/local.go +++ b/internal/bootstrap/local/local.go @@ -100,6 +100,7 @@ type CodesphereEnvironment struct { ArgoCDRegistryURL string `json:"-"` } +// NewLocalBootstrapper creates a bootstrapper for a local Codesphere environment. func NewLocalBootstrapper(ctx context.Context, stlog *bootstrap.StepLogger, kubeClient client.Client, restConfig *rest.Config, fw util.FileIO, icg installer.InstallConfigManager, helm installer.HelmClient, env *CodesphereEnvironment, verbose bool) *LocalBootstrapper { return &LocalBootstrapper{ ctx: ctx, diff --git a/internal/installer/codesphere_test.go b/internal/installer/codesphere_test.go index 6cf4df9e6..7e02f7a76 100644 --- a/internal/installer/codesphere_test.go +++ b/internal/installer/codesphere_test.go @@ -20,17 +20,20 @@ var _ = Describe("Codesphere installer", func() { for _, name := range []string{"deps.tar.gz", "private-cloud-installer.js", "node"} { Expect(os.WriteFile(filepath.Join(packageDir, name), nil, 0600)).To(Succeed()) } + entries, err := os.ReadDir(packageDir) Expect(err).NotTo(HaveOccurred()) fileIO := util.NewMockFileIO(GinkgoT()) fileIO.EXPECT().Exists(packageDir).Return(true) fileIO.EXPECT().ReadDir(packageDir).Return(entries, nil) + packageManager := installer.NewMockPackageManager(GinkgoT()) packageManager.EXPECT().Extract(false, true).Return(nil) packageManager.EXPECT().GetWorkDir().Return(packageDir) packageManager.EXPECT().FileIO().Return(fileIO).Twice() packageManager.EXPECT().ExtractDependency("bom.json", false, true).Return(nil) + ci := &installer.CodesphereInstaller{Verbose: true} err = ci.ExtractAndValidatePackage(packageManager) diff --git a/internal/installer/package.go b/internal/installer/package.go index 7cdfd083d..b4ba769bd 100644 --- a/internal/installer/package.go +++ b/internal/installer/package.go @@ -102,6 +102,7 @@ func (p *Package) Extract(force bool, verbose bool) error { depsArchivePath := path.Join(workDir, depsTar) if p.fileIO.Exists(depsArchivePath) { depsTargetDir := path.Join(workDir, depsDir) + err = util.ExtractTarGz(p.fileIO, depsArchivePath, depsTargetDir, verbose) if err != nil { return fmt.Errorf("failed to extract deps.tar.gz to %s: %w", depsTargetDir, err) @@ -135,6 +136,7 @@ func (p *Package) ExtractDependency(file string, force bool, verbose bool) error // ExtractOciImageIndex extracts and parses the OCI image index from the given image file path. func (p *Package) ExtractOciImageIndex(imagefile string, verbose bool) (files.OCIImageIndex, error) { var ociImageIndex files.OCIImageIndex + err := util.ExtractTarSingleFile(p.fileIO, imagefile, "index.json", filepath.Dir(imagefile), verbose) if err != nil { return ociImageIndex, fmt.Errorf("failed to extract index.json: %w", err) @@ -173,6 +175,7 @@ func (p *Package) GetFullImageTag(baseimage string) (string, error) { const baseimagePath = "./codesphere/images" +// GetBaseimagePath extracts the selected base image and returns its local path. func (p *Package) GetBaseimagePath(baseimage string, force bool, verbose bool) (string, error) { if baseimage == "" { return "", fmt.Errorf("baseimage not specified") @@ -183,6 +186,7 @@ func (p *Package) GetBaseimagePath(baseimage string, force bool, verbose bool) ( } baseImageTarPath := path.Join(baseimagePath, baseimage) + err := p.ExtractDependency(baseImageTarPath, force, verbose) if err != nil { return "", fmt.Errorf("failed to extract package to workdir: %w", err) diff --git a/internal/util/tar.go b/internal/util/tar.go index ccd436690..c372937b1 100644 --- a/internal/util/tar.go +++ b/internal/util/tar.go @@ -108,20 +108,24 @@ func extractEntry(header *tar.Header, targetPath string, fileIo FileIO, tr *tar. // ExtractTarGzSingleFile extracts a single specified file from a .tar.gz archive to the destination directory. func ExtractTarGzSingleFile(fileIo FileIO, archiveFile, fileToExtract, destDir string, verbose bool) error { destDir = filepath.Clean(destDir) + tr, err := openTarGz(archiveFile, fileIo, verbose) if err != nil { return err } + return extractTarSingleFile(fileIo, tr, fileToExtract, destDir, verbose) } // ExtractTarSingleFile extracts a single specified file from a .tar archive to the destination directory. func ExtractTarSingleFile(fileIo FileIO, archiveFile, fileToExtract, destDir string, verbose bool) error { destDir = filepath.Clean(destDir) + tr, err := openTar(archiveFile, fileIo, verbose) if err != nil { return err } + return extractTarSingleFile(fileIo, tr, fileToExtract, destDir, verbose) } diff --git a/internal/util/tar_test.go b/internal/util/tar_test.go index 181bc0832..3ba48d561 100644 --- a/internal/util/tar_test.go +++ b/internal/util/tar_test.go @@ -96,9 +96,11 @@ var _ = Describe("Tar", func() { tempDir := GinkgoT().TempDir() archivePath = filepath.Join(tempDir, "test.tar.gz") destination = filepath.Join(tempDir, "extracted") + Expect(os.WriteFile(archivePath, archiveData, 0600)).To(Succeed()) previousLogWriter := log.Writer() + log.SetOutput(&logOutput) DeferCleanup(func() { log.SetOutput(previousLogWriter) }) })