Factor out export command control flow
The export command works the same way for most (all?) types. I have
made it generic and moved it into export.go, then ported
{export,create}_auto_image{repository,policy}.go to use it.
Signed-off-by: Michael Bridgen <michael@weave.works>
This commit is contained in:
@@ -98,7 +98,7 @@ func createAutoImagePolicyRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
if export {
|
||||
return exportImagePolicy(policy) // defined with export command
|
||||
return printExport(exportImagePolicy(&policy))
|
||||
}
|
||||
|
||||
// I don't need these until attempting to upsert the object, but
|
||||
|
||||
@@ -103,7 +103,7 @@ func createAutoImageRepositoryRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
if export {
|
||||
return exportImageRepo(repo) // defined with export command
|
||||
return printExport(exportImageRepository(&repo))
|
||||
}
|
||||
|
||||
// I don't need these until attempting to upsert the object, but
|
||||
|
||||
@@ -18,8 +18,15 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
)
|
||||
|
||||
var exportCmd = &cobra.Command{
|
||||
@@ -38,6 +45,80 @@ func init() {
|
||||
rootCmd.AddCommand(exportCmd)
|
||||
}
|
||||
|
||||
// exportable represents a type that you can fetch from the Kubernetes
|
||||
// API, then tidy up for serialising.
|
||||
type exportable interface {
|
||||
objectContainer
|
||||
Export() interface{}
|
||||
}
|
||||
|
||||
// exportableAt represents a type that has a list of values, each of
|
||||
// which is exportable.
|
||||
type exportableAt interface {
|
||||
objectContainer
|
||||
Len() int
|
||||
ExportAt(i int) interface{}
|
||||
}
|
||||
|
||||
type exportCommand struct {
|
||||
object exportable
|
||||
list exportableAt
|
||||
}
|
||||
|
||||
func (export exportCommand) run(cmd *cobra.Command, args []string) error {
|
||||
if !exportAll && len(args) < 1 {
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exportAll {
|
||||
err = kubeClient.List(ctx, export.list.AsClientObject(), client.InNamespace(namespace))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if export.list.Len() == 0 {
|
||||
logger.Failuref("no objects found in %s namespace", namespace)
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < export.list.Len(); i++ {
|
||||
if err = printExport(export.list.ExportAt(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
name := args[0]
|
||||
namespacedName := types.NamespacedName{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
}
|
||||
err = kubeClient.Get(ctx, namespacedName, export.object.AsClientObject())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printExport(export.object.Export())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printExport(export interface{}) error {
|
||||
data, err := yaml.Marshal(export)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("---")
|
||||
fmt.Println(resourceToString(data))
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceToString(data []byte) string {
|
||||
data = bytes.Replace(data, []byte(" creationTimestamp: null\n"), []byte(""), 1)
|
||||
data = bytes.Replace(data, []byte("status: {}\n"), []byte(""), 1)
|
||||
|
||||
@@ -17,16 +17,10 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -40,60 +34,19 @@ var exportImagePolicyCmd = &cobra.Command{
|
||||
# Export a specific policy
|
||||
flux export auto image-policy alpine1x > alpine1x.yaml
|
||||
`,
|
||||
RunE: exportImagePolicyRun,
|
||||
RunE: exportCommand{
|
||||
object: exportableImagePolicy{&imagev1.ImagePolicy{}},
|
||||
list: exportableImagePolicyList{&imagev1.ImagePolicyList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
func init() {
|
||||
exportAutoCmd.AddCommand(exportImagePolicyCmd)
|
||||
}
|
||||
|
||||
func exportImagePolicyRun(cmd *cobra.Command, args []string) error {
|
||||
if !exportAll && len(args) < 1 {
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exportAll {
|
||||
var list imagev1.ImagePolicyList
|
||||
err = kubeClient.List(ctx, &list, client.InNamespace(namespace))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(list.Items) == 0 {
|
||||
logger.Failuref("no imagepolicy objects found in %s namespace", namespace)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, policy := range list.Items {
|
||||
if err := exportImagePolicy(policy); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
name := args[0]
|
||||
namespacedName := types.NamespacedName{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
}
|
||||
var policy imagev1.ImagePolicy
|
||||
err = kubeClient.Get(ctx, namespacedName, &policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return exportImagePolicy(policy)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportImagePolicy(policy imagev1.ImagePolicy) error {
|
||||
// Export returns a ImagePolicy value which has extraneous information
|
||||
// stripped out.
|
||||
func exportImagePolicy(item *imagev1.ImagePolicy) interface{} {
|
||||
gvk := imagev1.GroupVersion.WithKind(imagev1.ImagePolicyKind)
|
||||
export := imagev1.ImagePolicy{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
@@ -101,20 +54,40 @@ func exportImagePolicy(policy imagev1.ImagePolicy) error {
|
||||
APIVersion: gvk.GroupVersion().String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: policy.Name,
|
||||
Namespace: policy.Namespace,
|
||||
Labels: policy.Labels,
|
||||
Annotations: policy.Annotations,
|
||||
Name: item.Name,
|
||||
Namespace: item.Namespace,
|
||||
Labels: item.Labels,
|
||||
Annotations: item.Annotations,
|
||||
},
|
||||
Spec: policy.Spec,
|
||||
Spec: item.Spec,
|
||||
}
|
||||
|
||||
data, err := yaml.Marshal(export)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("---")
|
||||
fmt.Println(resourceToString(data))
|
||||
return nil
|
||||
return export
|
||||
}
|
||||
|
||||
type exportableImagePolicy struct {
|
||||
policy *imagev1.ImagePolicy
|
||||
}
|
||||
|
||||
func (ex exportableImagePolicy) AsClientObject() runtime.Object {
|
||||
return ex.policy
|
||||
}
|
||||
|
||||
func (ex exportableImagePolicy) Export() interface{} {
|
||||
return exportImagePolicy(ex.policy)
|
||||
}
|
||||
|
||||
type exportableImagePolicyList struct {
|
||||
list *imagev1.ImagePolicyList
|
||||
}
|
||||
|
||||
func (ex exportableImagePolicyList) AsClientObject() runtime.Object {
|
||||
return ex.list
|
||||
}
|
||||
|
||||
func (ex exportableImagePolicyList) Len() int {
|
||||
return len(ex.list.Items)
|
||||
}
|
||||
|
||||
func (ex exportableImagePolicyList) ExportAt(i int) interface{} {
|
||||
return exportImagePolicy(&ex.list.Items[i])
|
||||
}
|
||||
|
||||
@@ -17,16 +17,10 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/fluxcd/flux2/internal/utils"
|
||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -40,60 +34,17 @@ var exportImageRepositoryCmd = &cobra.Command{
|
||||
# Export a Provider
|
||||
flux export auto image-repository alpine > alpine.yaml
|
||||
`,
|
||||
RunE: exportImageRepositoryCmdRun,
|
||||
RunE: exportCommand{
|
||||
object: exportableImageRepository{&imagev1.ImageRepository{}},
|
||||
list: exportableImageRepositoryList{&imagev1.ImageRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
func init() {
|
||||
exportAutoCmd.AddCommand(exportImageRepositoryCmd)
|
||||
}
|
||||
|
||||
func exportImageRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if !exportAll && len(args) < 1 {
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
kubeClient, err := utils.KubeClient(kubeconfig, kubecontext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exportAll {
|
||||
var list imagev1.ImageRepositoryList
|
||||
err = kubeClient.List(ctx, &list, client.InNamespace(namespace))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(list.Items) == 0 {
|
||||
logger.Failuref("no imagerepository objects found in %s namespace", namespace)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, imageRepo := range list.Items {
|
||||
if err := exportImageRepo(imageRepo); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
name := args[0]
|
||||
namespacedName := types.NamespacedName{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
}
|
||||
var imageRepo imagev1.ImageRepository
|
||||
err = kubeClient.Get(ctx, namespacedName, &imageRepo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return exportImageRepo(imageRepo)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportImageRepo(repo imagev1.ImageRepository) error {
|
||||
func exportImageRepository(repo *imagev1.ImageRepository) interface{} {
|
||||
gvk := imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)
|
||||
export := imagev1.ImageRepository{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
@@ -108,13 +59,33 @@ func exportImageRepo(repo imagev1.ImageRepository) error {
|
||||
},
|
||||
Spec: repo.Spec,
|
||||
}
|
||||
|
||||
data, err := yaml.Marshal(export)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("---")
|
||||
fmt.Println(resourceToString(data))
|
||||
return nil
|
||||
return export
|
||||
}
|
||||
|
||||
type exportableImageRepository struct {
|
||||
repo *imagev1.ImageRepository
|
||||
}
|
||||
|
||||
func (ex exportableImageRepository) AsClientObject() runtime.Object {
|
||||
return ex.repo
|
||||
}
|
||||
|
||||
func (ex exportableImageRepository) Export() interface{} {
|
||||
return exportImageRepository(ex.repo)
|
||||
}
|
||||
|
||||
type exportableImageRepositoryList struct {
|
||||
list *imagev1.ImageRepositoryList
|
||||
}
|
||||
|
||||
func (ex exportableImageRepositoryList) AsClientObject() runtime.Object {
|
||||
return ex.list
|
||||
}
|
||||
|
||||
func (ex exportableImageRepositoryList) Len() int {
|
||||
return len(ex.list.Items)
|
||||
}
|
||||
|
||||
func (ex exportableImageRepositoryList) ExportAt(i int) interface{} {
|
||||
return exportImageRepository(&ex.list.Items[i])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user