diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9bccb6e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +# Set update schedule for GitHub Actions +version: 2 +updates: +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every day + interval: "daily" diff --git a/.github/workflows/ci-check-gomod-alt.yml b/.github/workflows/ci-check-gomod-alt.yml new file mode 100644 index 0000000..e57a5f4 --- /dev/null +++ b/.github/workflows/ci-check-gomod-alt.yml @@ -0,0 +1,13 @@ +# alternative workflow to ensure that the required status checks on the PR are handled +# see https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks +name: ci-check-gomod # same name +on: + pull_request: + paths-ignore: + - 'go.mod' +jobs: + gomodreplacements: + name: go.mod replacements + runs-on: ubuntu-20.04 + steps: + - run: 'echo "No check required" ' diff --git a/.github/workflows/ci-check-gomod.yml b/.github/workflows/ci-check-gomod.yml new file mode 100644 index 0000000..513a359 --- /dev/null +++ b/.github/workflows/ci-check-gomod.yml @@ -0,0 +1,22 @@ +name: ci-check-gomod +on: + pull_request: + branches: + - master + paths: + - 'go.mod' + +jobs: + gomodreplacements: + name: go.mod replacements + runs-on: ubuntu-20.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: check + run: | + if [[ -n "$(grep 'replace github.com/kubesaw/.*' go.mod || true)" ]]; then + echo "forbidden replacement in go.mod" + exit 1 + fi diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml new file mode 100644 index 0000000..6659aa5 --- /dev/null +++ b/.github/workflows/workflow.yml @@ -0,0 +1,86 @@ +name: ci-build +on: + push: + branches: + - master + tags-ignore: + - '*.*' + pull_request: + branches: + - master + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest ] + name: Test on ${{ matrix.os }} + + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: 1.20.x + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles ('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Build + run: | + make build + + - name: Test + run: | + make test-with-coverage + - name: Upload code coverage + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./out/coverage/coverage.txt + flags: unittests # optional + fail_ci_if_error: true # optional (default = false) + verbose: true # optional (default = false) + + golangci: + name: GolangCI Lint + runs-on: ubuntu-latest + + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: 1.20.x + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Lint + uses: golangci/golangci-lint-action@v4 + with: + version: v1.56.2 + skip-pkg-cache: true + skip-build-cache: true + args: --config=./.golangci.yml --verbose + + yammlint: + name: YAML Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install yamllint + run: pip install yamllint + + - name: Lint YAML files + run: yamllint -c .yamllint ./ diff --git a/.golangci.yml b/.golangci.yml index 50fd943..208602b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,7 +1,7 @@ service: project-path: github.com/kubesaw/ksctl prepare: # see https://github.com/golangci/golangci/wiki/Configuration#config-directives - - make generate + - make generate run: # timeout for analysis, e.g. 30s, 5m, default is 1m @@ -10,20 +10,20 @@ run: linters: enable: - - megacheck - - gocyclo - - gofmt - - revive - - misspell - - gosec + - megacheck + - gocyclo + - gofmt + - revive + - misspell + - gosec presets: # groups of linters. See https://golangci-lint.run/usage/linters/ - - bugs - - unused - disable: - - golint # deprecated, use 'revive' - - scopelint # deprecated, use 'exportloopref' - - contextcheck # too many false-positives - - noctx # not needed + - bugs + - unused + disable: + - golint # deprecated, use 'revive' + - scopelint # deprecated, use 'exportloopref' + - contextcheck # too many false-positives + - noctx # not needed # all available settings of specific linters linters-settings: @@ -35,5 +35,5 @@ linters-settings: check-exported: true revive: rules: - - name: dot-imports - disabled: true + - name: dot-imports + disabled: true diff --git a/.yamllint b/.yamllint index 167a611..3ace27d 100644 --- a/.yamllint +++ b/.yamllint @@ -1,10 +1,11 @@ ignore: | /tmp /.git - + rules: braces: enable - brackets: enable + brackets: + level: warning colons: enable commas: enable comments: disable diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index d52b347..b3cc140 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -188,7 +188,7 @@ func TestUpdateUserSignupLacksPermissions(t *testing.T) { }, "updated") // then - require.EqualError(t, err, "sandbox command failed: the token in your sandbox.yaml file is missing") + require.EqualError(t, err, "sandbox command failed: the token in your ksctl.yaml file is missing") AssertUserSignupSpec(t, fakeClient, userSignup) } diff --git a/pkg/cmd/adm/generate_cli_configs.go b/pkg/cmd/adm/generate_cli_configs.go index 612153d..d0667dd 100644 --- a/pkg/cmd/adm/generate_cli_configs.go +++ b/pkg/cmd/adm/generate_cli_configs.go @@ -36,8 +36,8 @@ func NewGenerateCliConfigsCmd() *cobra.Command { f := generateFlags{} command := &cobra.Command{ Use: "generate-cli-configs --sandbox-config=", - Short: "Generate sandbox.yaml files", - Long: `Generate sandbox.yaml files, that is used by ksctl, for every ServiceAccount defined in the given sandbox-config.yaml file`, + Short: "Generate ksctl.yaml files", + Long: `Generate ksctl.yaml files, that is used by ksctl, for every ServiceAccount defined in the given sandbox-config.yaml file`, Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, _ []string) error { term := ioutils.NewTerminal(cmd.InOrStdin, cmd.OutOrStdout) @@ -49,7 +49,7 @@ func NewGenerateCliConfigsCmd() *cobra.Command { command.Flags().BoolVarP(&f.dev, "dev", "d", false, "If running in a dev cluster") configDirPath := fmt.Sprintf("%s/src/github.com/kubesaw/ksctl/out/config", os.Getenv("GOPATH")) - command.Flags().StringVarP(&f.outDir, "out-dir", "o", configDirPath, "Directory where generated sandbox.yaml files should be stored") + command.Flags().StringVarP(&f.outDir, "out-dir", "o", configDirPath, "Directory where generated ksctl.yaml files should be stored") defaultKubeconfigPath := "" if home := homedir.HomeDir(); home != "" { @@ -94,7 +94,7 @@ func generate(term ioutils.Terminal, flags generateFlags, newClient NewClientFro kubeconfigPaths: flags.kubeconfigs, } - // sandboxUserConfigsPerName contains all sandboxUserConfig objects that will be marshalled to sandbox.yaml files + // sandboxUserConfigsPerName contains all sandboxUserConfig objects that will be marshalled to ksctl.yaml files sandboxUserConfigsPerName := map[string]configuration.SandboxUserConfig{} // use host API either from the sandbox-config.yaml or from kubeconfig if --dev flag was used @@ -148,11 +148,11 @@ func writeSandboxUserConfigs(term ioutils.Terminal, configDirPath string, sandbo if err != nil { return err } - path := pathDir + "/sandbox.yaml" + path := pathDir + "/ksctl.yaml" if err := os.WriteFile(path, content, 0600); err != nil { return err } - term.Printlnf("sandbox.yaml file for %s was stored in %s", name, path) + term.Printlnf("ksctl.yaml file for %s was stored in %s", name, path) } return nil } @@ -169,7 +169,7 @@ type generateContext struct { type tokenPerSA map[string]string func generateForCluster(ctx *generateContext, clusterType configuration.ClusterType, clusterName string, clusterSpec assets.ClusterConfig, sandboxUserConfigsPerName map[string]configuration.SandboxUserConfig) error { - ctx.PrintContextSeparatorf("Generating the content of the sandbox.yaml files for %s cluster running at %s", clusterName, clusterSpec.API) + ctx.PrintContextSeparatorf("Generating the content of the ksctl.yaml files for %s cluster running at %s", clusterName, clusterSpec.API) // find config we can build client for the cluster from externalClient, err := buildClientFromKubeconfigFiles(ctx, clusterSpec.API, ctx.kubeconfigPaths) diff --git a/pkg/cmd/adm/generate_cli_configs_test.go b/pkg/cmd/adm/generate_cli_configs_test.go index 98b7744..d17a3f5 100644 --- a/pkg/cmd/adm/generate_cli_configs_test.go +++ b/pkg/cmd/adm/generate_cli_configs_test.go @@ -237,7 +237,7 @@ func verifySandboxUserConfigFiles(t *testing.T, tempDir string, clusterAssertion require.NoError(t, err) assert.Len(t, userDirInfo, 1) - assert.Equal(t, "sandbox.yaml", userDirInfo[0].Name()) + assert.Equal(t, "ksctl.yaml", userDirInfo[0].Name()) content, err := os.ReadFile(path.Join(tempDir, userDir.Name(), userDirInfo[0].Name())) require.NoError(t, err) diff --git a/pkg/cmd/adm/unregister_member_test.go b/pkg/cmd/adm/unregister_member_test.go index 8e76b81..163041a 100644 --- a/pkg/cmd/adm/unregister_member_test.go +++ b/pkg/cmd/adm/unregister_member_test.go @@ -96,7 +96,7 @@ func TestUnregisterMemberWhenUnknownClusterName(t *testing.T) { // then require.Error(t, err) - assert.Contains(t, err.Error(), "the provided cluster-name 'some' is not present in your sandbox.yaml file.") + assert.Contains(t, err.Error(), "the provided cluster-name 'some' is not present in your ksctl.yaml file.") AssertToolchainClusterSpec(t, fakeClient, toolchainCluster) assert.NotContains(t, term.Output(), "!!! DANGER ZONE !!!") assert.NotContains(t, term.Output(), "THIS COMMAND WILL CAUSE UNREGISTER MEMBER CLUSTER FORM HOST CLUSTER. MAKE SURE THERE IS NO USERS LEFT IN THE MEMBER CLUSTER BEFORE UNREGISTERING IT") @@ -118,6 +118,6 @@ func TestUnregisterMemberLacksPermissions(t *testing.T) { err := UnregisterMemberCluster(ctx, "member1") // then - require.EqualError(t, err, "sandbox command failed: the token in your sandbox.yaml file is missing") + require.EqualError(t, err, "sandbox command failed: the token in your ksctl.yaml file is missing") AssertToolchainClusterSpec(t, fakeClient, toolchainCluster) } diff --git a/pkg/cmd/approve_test.go b/pkg/cmd/approve_test.go index f20aaf1..ab361ae 100644 --- a/pkg/cmd/approve_test.go +++ b/pkg/cmd/approve_test.go @@ -271,7 +271,7 @@ func TestApprove(t *testing.T) { // then require.Error(t, err) - assert.Contains(t, err.Error(), "the provided cluster-name 'non-existent-member' is not present in your sandbox.yaml file") + assert.Contains(t, err.Error(), "the provided cluster-name 'non-existent-member' is not present in your ksctl.yaml file") }) }) } diff --git a/pkg/cmd/ban_test.go b/pkg/cmd/ban_test.go index 0da3aba..2550755 100644 --- a/pkg/cmd/ban_test.go +++ b/pkg/cmd/ban_test.go @@ -224,6 +224,6 @@ func TestCreateBannedUserLacksPermissions(t *testing.T) { }) // then - require.EqualError(t, err, "sandbox command failed: the token in your sandbox.yaml file is missing") + require.EqualError(t, err, "sandbox command failed: the token in your ksctl.yaml file is missing") AssertUserSignupSpec(t, fakeClient, userSignup) } diff --git a/pkg/cmd/delete_test.go b/pkg/cmd/delete_test.go index bb8d980..b27dd9e 100644 --- a/pkg/cmd/delete_test.go +++ b/pkg/cmd/delete_test.go @@ -89,7 +89,7 @@ func TestDeleteLacksPermissions(t *testing.T) { err := cmd.Delete(ctx, userSignup.Name) // then - require.EqualError(t, err, "sandbox command failed: the token in your sandbox.yaml file is missing") + require.EqualError(t, err, "sandbox command failed: the token in your ksctl.yaml file is missing") AssertUserSignupSpec(t, fakeClient, userSignup) } diff --git a/pkg/cmd/retarget_test.go b/pkg/cmd/retarget_test.go index d5cfd7a..8322785 100644 --- a/pkg/cmd/retarget_test.go +++ b/pkg/cmd/retarget_test.go @@ -83,7 +83,7 @@ func TestRetarget(t *testing.T) { // then require.Error(t, err) - assert.Contains(t, err.Error(), "the provided cluster-name 'non-existent-member' is not present in your sandbox.yaml file") + assert.Contains(t, err.Error(), "the provided cluster-name 'non-existent-member' is not present in your ksctl.yaml file") }) t.Run("setting target cluster failed", func(t *testing.T) { diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go index 63d2ab0..90ca1cf 100644 --- a/pkg/cmd/root.go +++ b/pkg/cmd/root.go @@ -34,7 +34,7 @@ func Execute() { } func init() { - rootCmd.PersistentFlags().StringVar(&configuration.ConfigFileFlag, "config", "", "config file (default is $HOME/.sandbox.yaml)") + rootCmd.PersistentFlags().StringVar(&configuration.ConfigFileFlag, "config", "", "config file (default is $HOME/.ksctl.yaml)") rootCmd.PersistentFlags().BoolVarP(&configuration.Verbose, "verbose", "v", false, "print extra info/debug messages") // commands with go runtime client diff --git a/pkg/configuration/configuration.go b/pkg/configuration/configuration.go index 29857cd..376b7e2 100644 --- a/pkg/configuration/configuration.go +++ b/pkg/configuration/configuration.go @@ -33,7 +33,18 @@ func Load(term ioutils.Terminal) (SandboxUserConfig, string, error) { if err != nil { return SandboxUserConfig{}, "", errs.Wrap(err, "unable to read home directory") } - path = filepath.Join(home, ".sandbox.yaml") + path = filepath.Join(home, ".ksctl.yaml") + + if _, err := os.Stat(path); err != nil && os.IsNotExist(err) { + if _, err := os.Stat(filepath.Join(home, ".sandbox.yaml")); err != nil && !os.IsNotExist(err) { + return SandboxUserConfig{}, "", err + } else if err == nil { + path = filepath.Join(home, ".sandbox.yaml") + term.Println("The default location of ~/.sandbox.yaml file is deprecated. Rename it to ~/.ksctl.yaml") + } + } else if err != nil { + return SandboxUserConfig{}, "", err + } } info, err := os.Stat(path) @@ -112,7 +123,7 @@ func loadClusterAccessDefinition(sandboxUserConfig SandboxUserConfig, clusterNam if !ok { // if not found, then also try original format (to cover situation when camel case is used) if clusterDef, ok = sandboxUserConfig.ClusterAccessDefinitions[clusterName]; !ok { - return ClusterAccessDefinition{}, fmt.Errorf("the provided cluster-name '%s' is not present in your sandbox.yaml file. The available cluster names are\n"+ + return ClusterAccessDefinition{}, fmt.Errorf("the provided cluster-name '%s' is not present in your ksctl.yaml file. The available cluster names are\n"+ "------------------------\n%s\n"+ "------------------------", clusterName, strings.Join(getAllClusterNames(sandboxUserConfig), "\n")) } @@ -160,7 +171,7 @@ func LoadClusterConfig(term ioutils.Terminal, clusterName string) (ClusterConfig return ClusterConfig{}, err } if clusterDef.Token == "" { - return ClusterConfig{}, fmt.Errorf("sandbox command failed: the token in your sandbox.yaml file is missing") + return ClusterConfig{}, fmt.Errorf("sandbox command failed: the token in your ksctl.yaml file is missing") } var sandboxNamespace string if clusterName == HostName { diff --git a/pkg/configuration/configuration_test.go b/pkg/configuration/configuration_test.go index 09c04b1..0caeb6e 100644 --- a/pkg/configuration/configuration_test.go +++ b/pkg/configuration/configuration_test.go @@ -135,7 +135,7 @@ func TestLoadClusterConfig(t *testing.T) { cfg, err := configuration.LoadClusterConfig(term, clusterName) // then - require.EqualError(t, err, "sandbox command failed: the token in your sandbox.yaml file is missing") + require.EqualError(t, err, "sandbox command failed: the token in your ksctl.yaml file is missing") assert.Empty(t, cfg.Token) }) } @@ -186,7 +186,7 @@ func TestLoadClusterConfig(t *testing.T) { // then require.Error(t, err) - assert.Contains(t, err.Error(), "the provided cluster-name 'dummy' is not present in your sandbox.yaml file. The available cluster names are") + assert.Contains(t, err.Error(), "the provided cluster-name 'dummy' is not present in your ksctl.yaml file. The available cluster names are") }) for _, clusterConfigParam := range []ClusterDefinitionWithName{Host(), Member()} { @@ -223,7 +223,7 @@ func TestLoadingClusterConfigWithNonexistentClusterName(t *testing.T) { // then require.Error(t, err) - assert.Contains(t, err.Error(), "the provided cluster-name 'dummy' is not present in your sandbox.yaml file. The available cluster names are") + assert.Contains(t, err.Error(), "the provided cluster-name 'dummy' is not present in your ksctl.yaml file. The available cluster names are") assert.Contains(t, err.Error(), "host") assert.Contains(t, err.Error(), "member-1") assert.Empty(t, cfg.SandboxNamespace)