Add delete image-policy and refactor

This adds a command for deleting ImagePolicy objects. Since the
control flow for the command needs only a runtime.Object (and a name
for the type), it can be factored out.

I have made the argument (field in the deleteCommand struct) an
interface `objectContainer`, through which the command code gets a
`runtime.Object` to deserialise into (and delete). It could be simply
a `runtime.Object` here; however things like `getCommand` require
other methods, so it's convenient to have an interface for it.

Signed-off-by: Michael Bridgen <michael@weave.works>
pull/538/head
Michael Bridgen 4 years ago
parent 512761080e
commit 52145c045d

@ -17,7 +17,14 @@ limitations under the License.
package main package main
import ( import (
"context"
"fmt"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"github.com/fluxcd/flux2/internal/utils"
) )
var deleteCmd = &cobra.Command{ var deleteCmd = &cobra.Command{
@ -36,3 +43,52 @@ func init() {
rootCmd.AddCommand(deleteCmd) rootCmd.AddCommand(deleteCmd)
} }
type deleteCommand struct {
humanKind string // the kind being deleted, lowercase and spaced e.g., "image policy"
container objectContainer // for getting the value, and later deleting it
}
func (del deleteCommand) run(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("%s name is required", del.humanKind)
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
err = kubeClient.Get(ctx, namespacedName, del.container.AsClientObject())
if err != nil {
return err
}
if !deleteSilent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this " + del.humanKind,
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting %s %s in %s namespace", del.humanKind, name, namespace)
err = kubeClient.Delete(ctx, del.container.AsClientObject())
if err != nil {
return err
}
logger.Successf("%s deleted", del.humanKind)
return nil
}

@ -0,0 +1,40 @@
/*
Copyright 2020 The Flux 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 main
import (
"github.com/spf13/cobra"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
)
var deleteImagePolicyCmd = &cobra.Command{
Use: "image-policy [name]",
Short: "Delete an ImagePolicy object",
Long: "The delete auto image-policy command deletes the given ImagePolicy from the cluster.",
Example: ` # Delete an image policy
flux delete auto image-policy alpine3.x
`,
RunE: deleteCommand{
humanKind: "image policy",
container: genericContainer{&imagev1.ImagePolicy{}},
}.run,
}
func init() {
deleteAutoCmd.AddCommand(deleteImagePolicyCmd)
}

@ -17,14 +17,8 @@ limitations under the License.
package main package main
import ( import (
"context"
"fmt"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"github.com/fluxcd/flux2/internal/utils"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
) )
@ -35,54 +29,12 @@ var deleteImageRepositoryCmd = &cobra.Command{
Example: ` # Delete an image repository Example: ` # Delete an image repository
flux delete auto image-repository alpine flux delete auto image-repository alpine
`, `,
RunE: deleteImageRepositoryRun, RunE: deleteCommand{
humanKind: "image repository",
container: genericContainer{&imagev1.ImageRepository{}},
}.run,
} }
func init() { func init() {
deleteAutoCmd.AddCommand(deleteImageRepositoryCmd) deleteAutoCmd.AddCommand(deleteImageRepositoryCmd)
} }
func deleteImageRepositoryRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("image repository name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: namespace,
Name: name,
}
var repo imagev1.ImageRepository
err = kubeClient.Get(ctx, namespacedName, &repo)
if err != nil {
return err
}
if !deleteSilent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this image repository",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting image repository %s in %s namespace", name, namespace)
err = kubeClient.Delete(ctx, &repo)
if err != nil {
return err
}
logger.Successf("image repository deleted")
return nil
}

@ -23,7 +23,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta" apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/apis/meta"
@ -46,7 +45,7 @@ func init() {
} }
type summarisable interface { type summarisable interface {
AsObject() runtime.Object objectContainer
Len() int Len() int
SummariseAt(i int, includeNamespace bool) []string SummariseAt(i int, includeNamespace bool) []string
Headers(includeNamespace bool) []string Headers(includeNamespace bool) []string
@ -93,7 +92,7 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
if !allNamespaces { if !allNamespaces {
listOpts = append(listOpts, client.InNamespace(namespace)) listOpts = append(listOpts, client.InNamespace(namespace))
} }
err = kubeClient.List(ctx, get.list.AsObject(), listOpts...) err = kubeClient.List(ctx, get.list.AsClientObject(), listOpts...)
if err != nil { if err != nil {
return err return err
} }

@ -64,6 +64,6 @@ func (s imagePolicySummary) Headers(includeNamespace bool) []string {
return headers return headers
} }
func (s imagePolicySummary) AsObject() runtime.Object { func (s imagePolicySummary) AsClientObject() runtime.Object {
return s.ImagePolicyList return s.ImagePolicyList
} }

@ -73,6 +73,6 @@ func (s imageRepositorySummary) Headers(includeNamespace bool) []string {
return headers return headers
} }
func (s imageRepositorySummary) AsObject() runtime.Object { func (s imageRepositorySummary) AsClientObject() runtime.Object {
return s.ImageRepositoryList return s.ImageRepositoryList
} }

@ -0,0 +1,40 @@
/*
Copyright 2020 The Flux 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 main
import (
"k8s.io/apimachinery/pkg/runtime"
)
// objectContainer is an interface for a wrapper or alias from which we
// can get a controller-runtime deserialisable value. This is used so
// that you can wrap an API type to give it other useful methods, but
// still use values of the wrapper with `client.Client`, which only
// deals with types that have been added to the schema.
type objectContainer interface {
AsClientObject() runtime.Object
}
// genericContainer is an objectContainer for any runtime.Object. Use
// this if there are no other methods needed.
type genericContainer struct {
obj runtime.Object
}
func (c genericContainer) AsClientObject() runtime.Object {
return c.obj
}

@ -26,5 +26,6 @@ The delete auto sub-commands delete automation objects.
### SEE ALSO ### SEE ALSO
* [flux delete](flux_delete.md) - Delete sources and resources * [flux delete](flux_delete.md) - Delete sources and resources
* [flux delete auto image-policy](flux_delete_auto_image-policy.md) - Delete an ImagePolicy object
* [flux delete auto image-repository](flux_delete_auto_image-repository.md) - Delete an ImageRepository object * [flux delete auto image-repository](flux_delete_auto_image-repository.md) - Delete an ImageRepository object

@ -0,0 +1,41 @@
## flux delete auto image-policy
Delete an ImagePolicy object
### Synopsis
The delete auto image-policy command deletes the given ImagePolicy from the cluster.
```
flux delete auto image-policy [name] [flags]
```
### Examples
```
# Delete an image policy
flux delete auto image-policy alpine3.x
```
### Options
```
-h, --help help for image-policy
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
-s, --silent delete resource without asking for confirmation
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux delete auto](flux_delete_auto.md) - Delete automation objects
Loading…
Cancel
Save