From 0ea019970c06c8b669efdfd8ee714b8e5b5eae19 Mon Sep 17 00:00:00 2001 From: khanhtc1202 Date: Wed, 27 Apr 2022 14:30:45 +0700 Subject: [PATCH 1/2] Remove appconfig commands --- cmd/pipectl/main.go | 2 - pkg/app/pipectl/cmd/appconfig/appconfig.go | 44 ----- .../cmd/appconfig/migratefromdeployconfig.go | 186 ------------------ .../appconfig/migratefromdeployconfig_test.go | 163 --------------- pkg/app/pipectl/cmd/appconfig/rename.go | 172 ---------------- 5 files changed, 567 deletions(-) delete mode 100644 pkg/app/pipectl/cmd/appconfig/appconfig.go delete mode 100644 pkg/app/pipectl/cmd/appconfig/migratefromdeployconfig.go delete mode 100644 pkg/app/pipectl/cmd/appconfig/migratefromdeployconfig_test.go delete mode 100644 pkg/app/pipectl/cmd/appconfig/rename.go diff --git a/cmd/pipectl/main.go b/cmd/pipectl/main.go index 4eb8bbd32a..5557ad9865 100644 --- a/cmd/pipectl/main.go +++ b/cmd/pipectl/main.go @@ -18,7 +18,6 @@ import ( "fmt" "os" - "github.com/pipe-cd/pipecd/pkg/app/pipectl/cmd/appconfig" "github.com/pipe-cd/pipecd/pkg/app/pipectl/cmd/application" "github.com/pipe-cd/pipecd/pkg/app/pipectl/cmd/deployment" "github.com/pipe-cd/pipecd/pkg/app/pipectl/cmd/encrypt" @@ -41,7 +40,6 @@ func main() { planpreview.NewCommand(), piped.NewCommand(), encrypt.NewCommand(), - appconfig.NewCommand(), ) if err := app.Run(); err != nil { diff --git a/pkg/app/pipectl/cmd/appconfig/appconfig.go b/pkg/app/pipectl/cmd/appconfig/appconfig.go deleted file mode 100644 index 9d2ce87323..0000000000 --- a/pkg/app/pipectl/cmd/appconfig/appconfig.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2022 The PipeCD Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package appconfig - -import ( - "github.com/spf13/cobra" - - "github.com/pipe-cd/pipecd/pkg/app/pipectl/client" -) - -type command struct { - clientOptions *client.Options -} - -func NewCommand() *cobra.Command { - c := &command{ - clientOptions: &client.Options{}, - } - cmd := &cobra.Command{ - Use: "app-config", - Short: "Interact with application configuration file locally.", - } - - cmd.AddCommand( - newMigrateCommand(c), - newRenameCommand(c), - ) - - c.clientOptions.RegisterPersistentFlags(cmd) - - return cmd -} diff --git a/pkg/app/pipectl/cmd/appconfig/migratefromdeployconfig.go b/pkg/app/pipectl/cmd/appconfig/migratefromdeployconfig.go deleted file mode 100644 index 1278c675a3..0000000000 --- a/pkg/app/pipectl/cmd/appconfig/migratefromdeployconfig.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2022 The PipeCD Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package appconfig - -import ( - "bufio" - "bytes" - "context" - "fmt" - "io" - "os" - "path/filepath" - "strings" - - "github.com/spf13/cobra" - - "github.com/pipe-cd/pipecd/pkg/app/server/service/apiservice" - "github.com/pipe-cd/pipecd/pkg/cli" -) - -type migrateFromDeployConfig struct { - root *command - - repoRootPath string - repoID string - envName string - stdout io.Writer -} - -func newMigrateCommand(root *command) *cobra.Command { - m := &migrateFromDeployConfig{ - root: root, - stdout: os.Stdout, - } - cmd := &cobra.Command{ - Use: "migrate-from-deploy-config", - Short: "Migrate local deployment configuration files to application configuration files. Basically this finds all deployment configuration files to add name field and env label to them.", - RunE: cli.WithContext(m.run), - } - - cmd.Flags().StringVar(&m.repoRootPath, "repo-root-path", m.repoRootPath, "The absolute path to the root directory of the Git repository.") - cmd.Flags().StringVar(&m.repoID, "repo-id", m.repoID, "The repository ID that is being registered in Piped config.") - cmd.Flags().StringVar(&m.envName, "env-name", m.envName, "The environment name.") - - cmd.MarkFlagRequired("repo-root-path") - cmd.MarkFlagRequired("repo-id") - cmd.MarkFlagRequired("env-name") - - return cmd -} - -func (m *migrateFromDeployConfig) run(ctx context.Context, _ cli.Input) error { - cli, err := m.root.clientOptions.NewClient(ctx) - if err != nil { - return fmt.Errorf("failed to initialize client: %w", err) - } - defer cli.Close() - - fmt.Fprintln(m.stdout, "Start finding and migrating deployment configuration files to application configuration files...") - - var cursor string - var appConfigs = make(map[string][]byte, 0) - for { - req := &apiservice.ListApplicationsRequest{ - EnvName: m.envName, - Cursor: cursor, - } - resp, err := cli.ListApplications(ctx, req) - if err != nil { - return fmt.Errorf("failed to list application: %w", err) - } - - for _, app := range resp.Applications { - if app.GitPath.Repo.Id != m.repoID { - continue - } - - path := filepath.Join(m.repoRootPath, app.GitPath.GetApplicationConfigFilePath()) - oriData, err := os.ReadFile(path) - if err != nil { - return err - } - - newData, err := convert(oriData, app.Name, m.envName, app.Description) - if err != nil { - return err - } - appConfigs[path] = newData - } - if resp.Cursor == "" { - break - } - cursor = resp.Cursor - } - - if len(appConfigs) == 0 { - fmt.Println("There is no applications to migrate") - return nil - } - - for p, data := range appConfigs { - info, err := os.Stat(p) - if err != nil { - return err - } - if err := os.WriteFile(p, data, info.Mode()); err != nil { - return err - } - } - - fmt.Fprintf(m.stdout, "Successfully migrated %d applications\n", len(appConfigs)) - return nil -} - -func convert(data []byte, name, env, description string) ([]byte, error) { - var out strings.Builder - var shouldWrite, done bool - - scanner := bufio.NewScanner(bytes.NewReader(data)) - for scanner.Scan() { - line := scanner.Text() - if shouldWrite { - indent, ok := determineIndent(line) - if !ok { - fmt.Fprintf(&out, "%s\n", line) - continue - } - - writeNewFields(&out, name, env, description, indent) - shouldWrite = false - done = true - } - - fmt.Fprintf(&out, "%s\n", line) - if done { - continue - } - if strings.HasPrefix(line, "spec:") { - shouldWrite = true - } - } - - if err := scanner.Err(); err != nil { - return nil, err - } - return []byte(out.String()), nil -} - -func determineIndent(line string) (string, bool) { - noIndentLine := strings.TrimLeft(line, " \t") - // In case of just an empty line. - if noIndentLine == "" { - return "", false - } - // In case of just a comment. - if strings.HasPrefix(noIndentLine, "#") { - return "", false - } - return line[:len(line)-len(noIndentLine)], true -} - -func writeNewFields(out io.Writer, name, env, description, indent string) { - doubleIndent := strings.Repeat(indent, 2) - - fmt.Fprintf(out, "%sname: %s\n", indent, name) - fmt.Fprintf(out, "%slabels:\n", indent) - fmt.Fprintf(out, "%senv: %s\n", doubleIndent, env) - if description != "" { - fmt.Fprintf(out, "%sdescription: |\n", indent) - for _, s := range strings.Split(description, "\n") { - fmt.Fprintf(out, "%s%s\n", doubleIndent, s) - } - } -} diff --git a/pkg/app/pipectl/cmd/appconfig/migratefromdeployconfig_test.go b/pkg/app/pipectl/cmd/appconfig/migratefromdeployconfig_test.go deleted file mode 100644 index 2c1af69a6f..0000000000 --- a/pkg/app/pipectl/cmd/appconfig/migratefromdeployconfig_test.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2022 The PipeCD Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package appconfig - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestDetermineIndent(t *testing.T) { - testcases := []struct { - name string - line string - indent string - found bool - }{ - { - name: "empty string", - line: "", - indent: "", - found: false, - }, - { - name: "contains only space", - line: " ", - indent: "", - found: false, - }, - { - name: "comment", - line: " # This is a comment", - indent: "", - found: false, - }, - { - name: "indent just contains spaces", - line: " foo:", - indent: " ", - found: true, - }, - { - name: "indent just contains tab", - line: " foo:", - indent: " ", - found: true, - }, - { - name: "indent contains both space and tab", - line: " foo:", - indent: " ", - found: true, - }, - } - - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - got, found := determineIndent(tc.line) - assert.Equal(t, tc.indent, got) - assert.Equal(t, tc.found, found) - }) - } -} - -func TestConvert(t *testing.T) { - testcases := []struct { - name string - deployConfig string - appName string - appEnv string - appDescription string - appConfig string - }{ - { - name: "has description", - deployConfig: ` -# Deploy plain-yaml manifests in the application directory -# without using pipeline. -apiVersion: pipecd.dev/v1beta1 -kind: KubernetesApp -spec: - input: - manifests: - - deployment.yaml - - service.yaml - kubectlVersion: 1.18.5 -`, - appName: "test-name", - appEnv: "test-env", - appDescription: "test-description", - appConfig: ` -# Deploy plain-yaml manifests in the application directory -# without using pipeline. -apiVersion: pipecd.dev/v1beta1 -kind: KubernetesApp -spec: - name: test-name - labels: - env: test-env - description: | - test-description - input: - manifests: - - deployment.yaml - - service.yaml - kubectlVersion: 1.18.5 -`, - }, - { - name: "no description", - deployConfig: ` -# Deploy plain-yaml manifests in the application directory -# without using pipeline. -apiVersion: pipecd.dev/v1beta1 -kind: KubernetesApp -spec: - input: - manifests: - - deployment.yaml - - service.yaml - kubectlVersion: 1.18.5 -`, - appName: "test-name", - appEnv: "test-env", - appConfig: ` -# Deploy plain-yaml manifests in the application directory -# without using pipeline. -apiVersion: pipecd.dev/v1beta1 -kind: KubernetesApp -spec: - name: test-name - labels: - env: test-env - input: - manifests: - - deployment.yaml - - service.yaml - kubectlVersion: 1.18.5 -`, - }, - } - - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - got, err := convert([]byte(tc.deployConfig), tc.appName, tc.appEnv, tc.appDescription) - assert.Equal(t, tc.appConfig, string(got)) - require.NoError(t, err) - }) - } -} diff --git a/pkg/app/pipectl/cmd/appconfig/rename.go b/pkg/app/pipectl/cmd/appconfig/rename.go deleted file mode 100644 index 89510b2832..0000000000 --- a/pkg/app/pipectl/cmd/appconfig/rename.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2022 The PipeCD Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package appconfig - -import ( - "context" - "errors" - "fmt" - "io" - "os" - "path/filepath" - - "github.com/spf13/cobra" - - "github.com/pipe-cd/pipecd/pkg/app/server/service/apiservice" - "github.com/pipe-cd/pipecd/pkg/cli" - "github.com/pipe-cd/pipecd/pkg/model" -) - -type rename struct { - root *command - - repoRootPath string - repoID string - envName string - before string - after string - updateOnLocal bool - updateOnControlPlane bool - stdout io.Writer -} - -func newRenameCommand(root *command) *cobra.Command { - c := &rename{ - root: root, - stdout: os.Stdout, - } - cmd := &cobra.Command{ - Use: "rename", - Short: "Finds all applications that has the given configuration file name to change.", - RunE: cli.WithContext(c.run), - } - - cmd.Flags().StringVar(&c.repoRootPath, "repo-root-path", c.repoRootPath, "The absolute path to the root directory of the Git repository.") - cmd.Flags().StringVar(&c.repoID, "repo-id", c.repoID, "The repository ID that is being registered in Piped config.") - cmd.Flags().StringVar(&c.envName, "env-name", c.envName, "The environment name.") - cmd.Flags().StringVar(&c.before, "before", c.before, "The current name of configuration file.") - cmd.Flags().StringVar(&c.after, "after", c.after, "The new name of configuration file.") - cmd.Flags().BoolVar(&c.updateOnLocal, "update-on-local", c.updateOnLocal, "Whether to rename files in Git locally.") - cmd.Flags().BoolVar(&c.updateOnControlPlane, "update-on-control-plane", c.updateOnControlPlane, "Whether to update application information on control plane to use the new name.") - - cmd.MarkFlagRequired("repo-root-path") - cmd.MarkFlagRequired("repo-id") - cmd.MarkFlagRequired("before") - cmd.MarkFlagRequired("after") - - return cmd -} - -func (c *rename) run(ctx context.Context, _ cli.Input) error { - if !c.updateOnLocal && !c.updateOnControlPlane { - fmt.Fprintln(c.stdout, "Nothing to do since both --update-on-local and --update-on-control-plane were set to false.") - return nil - } - - cli, err := c.root.clientOptions.NewClient(ctx) - if err != nil { - return fmt.Errorf("failed to initialize client: %w", err) - } - defer cli.Close() - - fmt.Fprintln(c.stdout, "Start finding applications to rename their configuration files...") - - var ( - cursor string - targets []*model.Application - ) - - for { - req := &apiservice.ListApplicationsRequest{ - EnvName: c.envName, - Cursor: cursor, - } - resp, err := cli.ListApplications(ctx, req) - if err != nil { - return fmt.Errorf("failed to list application: %w", err) - } - for _, app := range resp.Applications { - if app.GitPath.Repo.Id != c.repoID { - continue - } - if app.GitPath.GetApplicationConfigFilename() != c.before { - continue - } - targets = append(targets, app) - } - if resp.Cursor == "" { - break - } - cursor = resp.Cursor - } - - fmt.Fprintf(c.stdout, "Found %d applications to update\n", len(targets)) - if len(targets) == 0 { - return nil - } - - if c.updateOnLocal { - for i, app := range targets { - // Ensure the existence of the current configuration file. - var ( - oldRelPath = app.GitPath.GetApplicationConfigFilePath() - oldPath = filepath.Join(c.repoRootPath, oldRelPath) - ) - if _, err := os.Stat(oldPath); err != nil { - return err - } - - // Ensure that the new name is not conflicting with any existing files. - var ( - newRelPath = filepath.Join(app.GitPath.Path, c.after) - newPath = filepath.Join(c.repoRootPath, newRelPath) - ) - _, err := os.Stat(newPath) - if err == nil { - return fmt.Errorf("unable to use the new name %q since it will override %s", c.after, newPath) - } - if !errors.Is(err, os.ErrNotExist) { - return err - } - - // Rename file locally. - if err := os.Rename(oldPath, newPath); err != nil { - return err - } - fmt.Fprintf(c.stdout, "%d. renamed %s to %s\n", i+1, oldRelPath, newRelPath) - } - fmt.Fprintf(c.stdout, "Successfully renamed %d applications locally\n", len(targets)) - } - - if c.updateOnControlPlane { - limit := 20 - for i := 0; i < len(targets); i += limit { - req := &apiservice.RenameApplicationConfigFileRequest{ - ApplicationIds: make([]string, 0, limit), - NewFilename: c.after, - } - for j := i; j < len(targets) && j < i+limit; j++ { - req.ApplicationIds = append(req.ApplicationIds, targets[j].Id) - } - _, err := cli.RenameApplicationConfigFile(ctx, req) - if err != nil { - return fmt.Errorf("failed to update the configuration file name on the control plane: %w", err) - } - } - fmt.Fprintf(c.stdout, "Successfully renamed %d applications on the control plane\n", len(targets)) - } - - return nil -} From 8566bd36bc814fe601cac39febebe98ea053c1e6 Mon Sep 17 00:00:00 2001 From: khanhtc1202 Date: Wed, 27 Apr 2022 15:29:03 +0700 Subject: [PATCH 2/2] Remove docs for removed comamnds --- .../docs-dev/user-guide/command-line-tool.md | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/docs/content/en/docs-dev/user-guide/command-line-tool.md b/docs/content/en/docs-dev/user-guide/command-line-tool.md index d4fcab447b..e502587e29 100644 --- a/docs/content/en/docs-dev/user-guide/command-line-tool.md +++ b/docs/content/en/docs-dev/user-guide/command-line-tool.md @@ -241,32 +241,6 @@ You can encrypt it the same way you do [from the web](/docs/user-guide/secret-ma --input-file={PATH_TO_SECRET_FILE} ``` -### Rename multiple application configuration files - - ``` console - pipectl app-config rename \ - --address={CONTROL_PLANE_API_ADDRESS} \ - --api-key={API_KEY} \ - --repo-root-path={ABSOLUTE_PATH_TO_ROOT_OF_REPOSITORY} \ - --repo-id={REPO_ID} \ - --env-name={ENV_NAME} \ # Optional. - --before=.pipe.yaml \ - --after=app.pipecd.yaml \ - --update-on-local=true \ # Whether to rename files in Git locally. - --update-on-control-plane=false # Whether to update application information on control plane to use the new name. - ``` - -### Migrating deployment configuration files to application configuration files - - ``` console - pipectl app-config migrate-from-deploy-config \ - --address={CONTROL_PLANE_API_ADDRESS} \ - --api-key={API_KEY} \ - --repo-root-path={ABSOLUTE_PATH_TO_ROOT_OF_REPOSITORY} \ - --repo-id={REPO_ID} \ - --env-name={ENV_NAME} - ``` - ### You want more? We always want to add more needed commands into pipectl. Please let us know what command you want to add by creating issues in the [pipe-cd/pipe ](https://github.com/pipe-cd/pipecd/issues) repository. We also welcome your pull request to add the command.