forked from notaryproject/notation
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add notation plugin uninstall command (notaryproject#842)
This PR is based on the spec PR: notaryproject#809. It adds the notation plugin uninstall command. Signed-off-by: Patrick Zheng <[email protected]> Signed-off-by: rgnote <[email protected]>
- Loading branch information
1 parent
2b533cf
commit 39ce373
Showing
10 changed files
with
219 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright The Notary Project 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 plugin | ||
|
||
import "github.com/spf13/cobra" | ||
|
||
func Cmd() *cobra.Command { | ||
command := &cobra.Command{ | ||
Use: "plugin", | ||
Short: "Manage plugins", | ||
} | ||
|
||
command.AddCommand( | ||
listCommand(), | ||
uninstallCommand(nil), | ||
) | ||
|
||
return command | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// Copyright The Notary Project 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 plugin | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/notaryproject/notation-go/dir" | ||
"github.com/notaryproject/notation-go/plugin" | ||
"github.com/notaryproject/notation/cmd/notation/internal/cmdutil" | ||
"github.com/notaryproject/notation/internal/cmd" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
type pluginUninstallOpts struct { | ||
cmd.LoggingFlagOpts | ||
pluginName string | ||
confirmed bool | ||
} | ||
|
||
func uninstallCommand(opts *pluginUninstallOpts) *cobra.Command { | ||
if opts == nil { | ||
opts = &pluginUninstallOpts{} | ||
} | ||
command := &cobra.Command{ | ||
Use: "uninstall [flags] <plugin_name>", | ||
Aliases: []string{"remove", "rm"}, | ||
Short: "Uninstall a plugin", | ||
Long: `Uninstall a plugin | ||
Example - Uninstall plugin: | ||
notation plugin uninstall wabbit-plugin | ||
`, | ||
Args: func(cmd *cobra.Command, args []string) error { | ||
if len(args) == 0 { | ||
return errors.New("plugin name is required") | ||
} | ||
if len(args) > 1 { | ||
return errors.New("only one plugin can be removed at a time") | ||
} | ||
opts.pluginName = args[0] | ||
return nil | ||
}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return uninstallPlugin(cmd, opts) | ||
}, | ||
} | ||
|
||
opts.LoggingFlagOpts.ApplyFlags(command.Flags()) | ||
command.Flags().BoolVarP(&opts.confirmed, "yes", "y", false, "do not prompt for confirmation") | ||
return command | ||
} | ||
|
||
func uninstallPlugin(command *cobra.Command, opts *pluginUninstallOpts) error { | ||
// set logger | ||
ctx := opts.LoggingFlagOpts.InitializeLogger(command.Context()) | ||
pluginName := opts.pluginName | ||
exist, err := checkPluginExistence(ctx, pluginName) | ||
if err != nil { | ||
return fmt.Errorf("failed to check plugin existence: %w", err) | ||
} | ||
if !exist { | ||
return fmt.Errorf("unable to find plugin %s.\nTo view a list of installed plugins, use `notation plugin list`", pluginName) | ||
} | ||
// core process | ||
prompt := fmt.Sprintf("Are you sure you want to uninstall plugin %q?", pluginName) | ||
confirmed, err := cmdutil.AskForConfirmation(os.Stdin, prompt, opts.confirmed) | ||
if err != nil { | ||
return fmt.Errorf("failed when asking for confirmation: %w", err) | ||
} | ||
if !confirmed { | ||
return nil | ||
} | ||
mgr := plugin.NewCLIManager(dir.PluginFS()) | ||
if err := mgr.Uninstall(ctx, pluginName); err != nil { | ||
return fmt.Errorf("failed to uninstall %s: %w", pluginName, err) | ||
} | ||
fmt.Printf("Successfully uninstalled plugin %s\n", pluginName) | ||
return nil | ||
} | ||
|
||
// checkPluginExistence returns true if plugin exists in the system | ||
func checkPluginExistence(ctx context.Context, pluginName string) (bool, error) { | ||
mgr := plugin.NewCLIManager(dir.PluginFS()) | ||
_, err := mgr.Get(ctx, pluginName) | ||
if err != nil { | ||
if errors.Is(err, os.ErrNotExist) { // plugin does not exist | ||
return false, nil | ||
} | ||
return false, err | ||
} | ||
return true, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,9 +71,9 @@ fi | |
# install dependency | ||
go install -mod=mod github.com/onsi/ginkgo/v2/[email protected] | ||
|
||
# build e2e plugin | ||
# build e2e plugin and tar.gz | ||
PLUGIN_NAME=e2e-plugin | ||
( cd $CWD/plugin && go build -o ./bin/$PLUGIN_NAME . && echo "e2e plugin built." ) | ||
( cd $CWD/plugin && go build -o ./bin/$PLUGIN_NAME . && echo "e2e plugin built." && tar --transform="flags=r;s|$PLUGIN_NAME|notation-$PLUGIN_NAME|" -czvf ./bin/$PLUGIN_NAME.tar.gz -C ./bin/ $PLUGIN_NAME) | ||
|
||
# setup registry | ||
case $REGISTRY_NAME in | ||
|
@@ -107,6 +107,7 @@ export NOTATION_E2E_OCI_LAYOUT_PATH=$CWD/testdata/registry/oci_layout | |
export NOTATION_E2E_TEST_REPO=e2e | ||
export NOTATION_E2E_TEST_TAG=v1 | ||
export NOTATION_E2E_PLUGIN_PATH=$CWD/plugin/bin/$PLUGIN_NAME | ||
export NOTATION_E2E_PLUGIN_TAR_GZ_PATH=$CWD/plugin/bin/$PLUGIN_NAME.tar.gz | ||
|
||
# run tests | ||
ginkgo -r -p -v |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright The Notary Project 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 plugin | ||
|
||
import ( | ||
. "github.com/notaryproject/notation/test/e2e/internal/notation" | ||
"github.com/notaryproject/notation/test/e2e/internal/utils" | ||
. "github.com/onsi/ginkgo/v2" | ||
) | ||
|
||
var _ = Describe("notation plugin uninstall", func() { | ||
It("with valid plugin name", func() { | ||
Host(nil, func(notation *utils.ExecOpts, _ *Artifact, vhost *utils.VirtualHost) { | ||
vhost.SetOption(AddPlugin(NotationE2EPluginPath)) | ||
notation.Exec("plugin", "uninstall", "--yes", "e2e-plugin"). | ||
MatchContent("Successfully uninstalled plugin e2e-plugin\n") | ||
}) | ||
}) | ||
|
||
It("with plugin does not exist", func() { | ||
Host(nil, func(notation *utils.ExecOpts, _ *Artifact, vhost *utils.VirtualHost) { | ||
notation.ExpectFailure().Exec("plugin", "uninstall", "--yes", "non-exist"). | ||
MatchErrContent("Error: unable to find plugin non-exist.\nTo view a list of installed plugins, use `notation plugin list`\n") | ||
}) | ||
}) | ||
|
||
}) |