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 {
|
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
|
// 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 {
|
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
|
// I don't need these until attempting to upsert the object, but
|
||||||
|
|||||||
@@ -18,8 +18,15 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"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{
|
var exportCmd = &cobra.Command{
|
||||||
@@ -38,6 +45,80 @@ func init() {
|
|||||||
rootCmd.AddCommand(exportCmd)
|
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 {
|
func resourceToString(data []byte) string {
|
||||||
data = bytes.Replace(data, []byte(" creationTimestamp: null\n"), []byte(""), 1)
|
data = bytes.Replace(data, []byte(" creationTimestamp: null\n"), []byte(""), 1)
|
||||||
data = bytes.Replace(data, []byte("status: {}\n"), []byte(""), 1)
|
data = bytes.Replace(data, []byte("status: {}\n"), []byte(""), 1)
|
||||||
|
|||||||
@@ -17,16 +17,10 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
"sigs.k8s.io/yaml"
|
|
||||||
|
|
||||||
"github.com/fluxcd/flux2/internal/utils"
|
|
||||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,60 +34,19 @@ var exportImagePolicyCmd = &cobra.Command{
|
|||||||
# Export a specific policy
|
# Export a specific policy
|
||||||
flux export auto image-policy alpine1x > alpine1x.yaml
|
flux export auto image-policy alpine1x > alpine1x.yaml
|
||||||
`,
|
`,
|
||||||
RunE: exportImagePolicyRun,
|
RunE: exportCommand{
|
||||||
|
object: exportableImagePolicy{&imagev1.ImagePolicy{}},
|
||||||
|
list: exportableImagePolicyList{&imagev1.ImagePolicyList{}},
|
||||||
|
}.run,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
exportAutoCmd.AddCommand(exportImagePolicyCmd)
|
exportAutoCmd.AddCommand(exportImagePolicyCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportImagePolicyRun(cmd *cobra.Command, args []string) error {
|
// Export returns a ImagePolicy value which has extraneous information
|
||||||
if !exportAll && len(args) < 1 {
|
// stripped out.
|
||||||
return fmt.Errorf("name is required")
|
func exportImagePolicy(item *imagev1.ImagePolicy) interface{} {
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
gvk := imagev1.GroupVersion.WithKind(imagev1.ImagePolicyKind)
|
gvk := imagev1.GroupVersion.WithKind(imagev1.ImagePolicyKind)
|
||||||
export := imagev1.ImagePolicy{
|
export := imagev1.ImagePolicy{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
@@ -101,20 +54,40 @@ func exportImagePolicy(policy imagev1.ImagePolicy) error {
|
|||||||
APIVersion: gvk.GroupVersion().String(),
|
APIVersion: gvk.GroupVersion().String(),
|
||||||
},
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: policy.Name,
|
Name: item.Name,
|
||||||
Namespace: policy.Namespace,
|
Namespace: item.Namespace,
|
||||||
Labels: policy.Labels,
|
Labels: item.Labels,
|
||||||
Annotations: policy.Annotations,
|
Annotations: item.Annotations,
|
||||||
},
|
},
|
||||||
Spec: policy.Spec,
|
Spec: item.Spec,
|
||||||
}
|
}
|
||||||
|
return export
|
||||||
data, err := yaml.Marshal(export)
|
}
|
||||||
if err != nil {
|
|
||||||
return err
|
type exportableImagePolicy struct {
|
||||||
}
|
policy *imagev1.ImagePolicy
|
||||||
|
}
|
||||||
fmt.Println("---")
|
|
||||||
fmt.Println(resourceToString(data))
|
func (ex exportableImagePolicy) AsClientObject() runtime.Object {
|
||||||
return nil
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
||||||
"sigs.k8s.io/yaml"
|
|
||||||
|
|
||||||
"github.com/fluxcd/flux2/internal/utils"
|
|
||||||
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,60 +34,17 @@ var exportImageRepositoryCmd = &cobra.Command{
|
|||||||
# Export a Provider
|
# Export a Provider
|
||||||
flux export auto image-repository alpine > alpine.yaml
|
flux export auto image-repository alpine > alpine.yaml
|
||||||
`,
|
`,
|
||||||
RunE: exportImageRepositoryCmdRun,
|
RunE: exportCommand{
|
||||||
|
object: exportableImageRepository{&imagev1.ImageRepository{}},
|
||||||
|
list: exportableImageRepositoryList{&imagev1.ImageRepositoryList{}},
|
||||||
|
}.run,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
exportAutoCmd.AddCommand(exportImageRepositoryCmd)
|
exportAutoCmd.AddCommand(exportImageRepositoryCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportImageRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
func exportImageRepository(repo *imagev1.ImageRepository) interface{} {
|
||||||
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 {
|
|
||||||
gvk := imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)
|
gvk := imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)
|
||||||
export := imagev1.ImageRepository{
|
export := imagev1.ImageRepository{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
@@ -108,13 +59,33 @@ func exportImageRepo(repo imagev1.ImageRepository) error {
|
|||||||
},
|
},
|
||||||
Spec: repo.Spec,
|
Spec: repo.Spec,
|
||||||
}
|
}
|
||||||
|
return export
|
||||||
data, err := yaml.Marshal(export)
|
}
|
||||||
if err != nil {
|
|
||||||
return err
|
type exportableImageRepository struct {
|
||||||
}
|
repo *imagev1.ImageRepository
|
||||||
|
}
|
||||||
fmt.Println("---")
|
|
||||||
fmt.Println(resourceToString(data))
|
func (ex exportableImageRepository) AsClientObject() runtime.Object {
|
||||||
return nil
|
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