Refactor all remaining create, delete, export, get command to use adapter

Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
pull/1149/head
Somtochi Onyekwere 4 years ago
parent c23e8c7ee1
commit 465eaa24d3

@ -0,0 +1,51 @@
/*
Copyright 2021 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 (
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// notificationv1.Alert
var alertType = apiType{
kind: notificationv1.AlertKind,
humanKind: "alert",
}
type alertAdapter struct {
*notificationv1.Alert
}
func (a alertAdapter) asClientObject() client.Object {
return a.Alert
}
// notificationv1.Alert
type alertListAdapter struct {
*notificationv1.AlertList
}
func (a alertListAdapter) asClientList() client.ObjectList {
return a.AlertList
}
func (a alertListAdapter) len() int {
return len(a.AlertList.Items)
}

@ -0,0 +1,51 @@
/*
Copyright 2021 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 (
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// notificationv1.Provider
var alertProviderType = apiType{
kind: notificationv1.ProviderKind,
humanKind: "alert provider",
}
type alertProviderAdapter struct {
*notificationv1.Provider
}
func (a alertProviderAdapter) asClientObject() client.Object {
return a.Provider
}
// notificationv1.Provider
type alertProviderListAdapter struct {
*notificationv1.ProviderList
}
func (a alertProviderListAdapter) asClientList() client.ObjectList {
return a.ProviderList
}
func (a alertProviderListAdapter) len() int {
return len(a.ProviderList.Items)
}

@ -116,7 +116,7 @@ func createAlertCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
return exportAlert(alert)
return printExport(exportAlert(&alert))
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

@ -113,7 +113,7 @@ func createAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
return exportAlertProvider(provider)
return printExport(exportAlertProvider(&provider))
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

@ -219,7 +219,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
return exportHelmRelease(helmRelease)
return printExport(exportHelmRelease(&helmRelease))
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

@ -211,7 +211,7 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
return exportKs(kustomization)
return printExport(exportKs(&kustomization))
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

@ -125,7 +125,7 @@ func createReceiverCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
return exportReceiver(receiver)
return printExport(exportReceiver(&receiver))
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

@ -144,7 +144,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
return exportBucket(*bucket)
return printExport(exportBucket(bucket))
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

@ -195,7 +195,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
return exportGit(gitRepository)
return printExport(exportGit(&gitRepository))
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

@ -137,7 +137,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
return exportHelmRepository(*helmRepository)
return printExport(exportHelmRepository(helmRepository))
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)

@ -17,15 +17,8 @@ limitations under the License.
package main
import (
"context"
"fmt"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/spf13/cobra"
)
var deleteAlertCmd = &cobra.Command{
@ -35,54 +28,12 @@ var deleteAlertCmd = &cobra.Command{
Example: ` # Delete an Alert and the Kubernetes resources created by it
flux delete alert main
`,
RunE: deleteAlertCmdRun,
RunE: deleteCommand{
apiType: alertType,
object: universalAdapter{&notificationv1.Alert{}},
}.run,
}
func init() {
deleteCmd.AddCommand(deleteAlertCmd)
}
func deleteAlertCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("alert name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var alert notificationv1.Alert
err = kubeClient.Get(ctx, namespacedName, &alert)
if err != nil {
return err
}
if !deleteArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Alert",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting alert %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &alert)
if err != nil {
return err
}
logger.Successf("alert deleted")
return nil
}

@ -17,15 +17,8 @@ limitations under the License.
package main
import (
"context"
"fmt"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/spf13/cobra"
)
var deleteAlertProviderCmd = &cobra.Command{
@ -35,54 +28,12 @@ var deleteAlertProviderCmd = &cobra.Command{
Example: ` # Delete a Provider and the Kubernetes resources created by it
flux delete alert-provider slack
`,
RunE: deleteAlertProviderCmdRun,
RunE: deleteCommand{
apiType: alertProviderType,
object: universalAdapter{&notificationv1.Provider{}},
}.run,
}
func init() {
deleteCmd.AddCommand(deleteAlertProviderCmd)
}
func deleteAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("provider name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var alertProvider notificationv1.Provider
err = kubeClient.Get(ctx, namespacedName, &alertProvider)
if err != nil {
return err
}
if !deleteArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Provider",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting provider %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &alertProvider)
if err != nil {
return err
}
logger.Successf("provider deleted")
return nil
}

@ -17,15 +17,8 @@ limitations under the License.
package main
import (
"context"
"fmt"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/spf13/cobra"
)
var deleteReceiverCmd = &cobra.Command{
@ -35,54 +28,12 @@ var deleteReceiverCmd = &cobra.Command{
Example: ` # Delete an Receiver and the Kubernetes resources created by it
flux delete receiver main
`,
RunE: deleteReceiverCmdRun,
RunE: deleteCommand{
apiType: receiverType,
object: universalAdapter{&notificationv1.Receiver{}},
}.run,
}
func init() {
deleteCmd.AddCommand(deleteReceiverCmd)
}
func deleteReceiverCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("receiver name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var receiver notificationv1.Receiver
err = kubeClient.Get(ctx, namespacedName, &receiver)
if err != nil {
return err
}
if !deleteArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this Receiver",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting receiver %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &receiver)
if err != nil {
return err
}
logger.Successf("receiver deleted")
return nil
}

@ -17,14 +17,8 @@ limitations under the License.
package main
import (
"context"
"fmt"
"github.com/fluxcd/flux2/internal/utils"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
)
var deleteSourceHelmCmd = &cobra.Command{
@ -43,48 +37,3 @@ var deleteSourceHelmCmd = &cobra.Command{
func init() {
deleteSourceCmd.AddCommand(deleteSourceHelmCmd)
}
func deleteSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("name is required")
}
name := args[0]
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var helmRepository sourcev1.HelmRepository
err = kubeClient.Get(ctx, namespacedName, &helmRepository)
if err != nil {
return err
}
if !deleteArgs.silent {
prompt := promptui.Prompt{
Label: "Are you sure you want to delete this source",
IsConfirm: true,
}
if _, err := prompt.Run(); err != nil {
return fmt.Errorf("aborting")
}
}
logger.Actionf("deleting source %s in %s namespace", name, rootArgs.namespace)
err = kubeClient.Delete(ctx, &helmRepository)
if err != nil {
return err
}
logger.Successf("source deleted")
return nil
}

@ -20,7 +20,6 @@ import (
"bytes"
"context"
"fmt"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
@ -86,8 +85,7 @@ func (export exportCommand) run(cmd *cobra.Command, args []string) error {
}
if export.list.len() == 0 {
logger.Failuref("no objects found in %s namespace", rootArgs.namespace)
return nil
return fmt.Errorf("no objects found in %s namespace", rootArgs.namespace)
}
for i := 0; i < export.list.len(); i++ {

@ -17,17 +17,9 @@ limitations under the License.
package main
import (
"context"
"fmt"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"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"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
)
var exportAlertCmd = &cobra.Command{
@ -40,60 +32,17 @@ var exportAlertCmd = &cobra.Command{
# Export a Alert
flux export alert main > main.yaml
`,
RunE: exportAlertCmdRun,
RunE: exportCommand{
object: alertAdapter{&notificationv1.Alert{}},
list: alertListAdapter{&notificationv1.AlertList{}},
}.run,
}
func init() {
exportCmd.AddCommand(exportAlertCmd)
}
func exportAlertCmdRun(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list notificationv1.AlertList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no alerts found in %s namespace", rootArgs.namespace)
return nil
}
for _, alert := range list.Items {
if err := exportAlert(alert); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var alert notificationv1.Alert
err = kubeClient.Get(ctx, namespacedName, &alert)
if err != nil {
return err
}
return exportAlert(alert)
}
return nil
}
func exportAlert(alert notificationv1.Alert) error {
func exportAlert(alert *notificationv1.Alert) interface{} {
gvk := notificationv1.GroupVersion.WithKind("Alert")
export := notificationv1.Alert{
TypeMeta: metav1.TypeMeta{
@ -109,12 +58,13 @@ func exportAlert(alert notificationv1.Alert) error {
Spec: alert.Spec,
}
data, err := yaml.Marshal(export)
if err != nil {
return err
}
return export
}
func (ex alertAdapter) export() interface{} {
return exportAlert(ex.Alert)
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
func (ex alertListAdapter) exportItem(i int) interface{} {
return exportAlert(&ex.AlertList.Items[i])
}

@ -17,17 +17,9 @@ limitations under the License.
package main
import (
"context"
"fmt"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"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"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
)
var exportAlertProviderCmd = &cobra.Command{
@ -40,60 +32,17 @@ var exportAlertProviderCmd = &cobra.Command{
# Export a Provider
flux export alert-provider slack > slack.yaml
`,
RunE: exportAlertProviderCmdRun,
RunE: exportCommand{
object: alertProviderAdapter{&notificationv1.Provider{}},
list: alertProviderListAdapter{&notificationv1.ProviderList{}},
}.run,
}
func init() {
exportCmd.AddCommand(exportAlertProviderCmd)
}
func exportAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list notificationv1.ProviderList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no alertproviders found in %s namespace", rootArgs.namespace)
return nil
}
for _, alertProvider := range list.Items {
if err := exportAlertProvider(alertProvider); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var alertProvider notificationv1.Provider
err = kubeClient.Get(ctx, namespacedName, &alertProvider)
if err != nil {
return err
}
return exportAlertProvider(alertProvider)
}
return nil
}
func exportAlertProvider(alertProvider notificationv1.Provider) error {
func exportAlertProvider(alertProvider *notificationv1.Provider) interface{} {
gvk := notificationv1.GroupVersion.WithKind("Provider")
export := notificationv1.Provider{
TypeMeta: metav1.TypeMeta{
@ -108,13 +57,13 @@ func exportAlertProvider(alertProvider notificationv1.Provider) error {
},
Spec: alertProvider.Spec,
}
return export
}
data, err := yaml.Marshal(export)
if err != nil {
return err
}
func (ex alertProviderAdapter) export() interface{} {
return exportAlertProvider(ex.Provider)
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
func (ex alertProviderListAdapter) exportItem(i int) interface{} {
return exportAlertProvider(&ex.ProviderList.Items[i])
}

@ -17,17 +17,9 @@ limitations under the License.
package main
import (
"context"
"fmt"
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
"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"
"github.com/fluxcd/flux2/internal/utils"
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
)
var exportHelmReleaseCmd = &cobra.Command{
@ -41,60 +33,17 @@ var exportHelmReleaseCmd = &cobra.Command{
# Export a HelmRelease
flux export hr my-app > app-release.yaml
`,
RunE: exportHelmReleaseCmdRun,
RunE: exportCommand{
object: helmReleaseAdapter{&helmv2.HelmRelease{}},
list: helmReleaseListAdapter{&helmv2.HelmReleaseList{}},
}.run,
}
func init() {
exportCmd.AddCommand(exportHelmReleaseCmd)
}
func exportHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list helmv2.HelmReleaseList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no helmrelease found in %s namespace", rootArgs.namespace)
return nil
}
for _, helmRelease := range list.Items {
if err := exportHelmRelease(helmRelease); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var helmRelease helmv2.HelmRelease
err = kubeClient.Get(ctx, namespacedName, &helmRelease)
if err != nil {
return err
}
return exportHelmRelease(helmRelease)
}
return nil
}
func exportHelmRelease(helmRelease helmv2.HelmRelease) error {
func exportHelmRelease(helmRelease *helmv2.HelmRelease) interface{} {
gvk := helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)
export := helmv2.HelmRelease{
TypeMeta: metav1.TypeMeta{
@ -109,13 +58,13 @@ func exportHelmRelease(helmRelease helmv2.HelmRelease) error {
},
Spec: helmRelease.Spec,
}
return export
}
data, err := yaml.Marshal(export)
if err != nil {
return err
}
func (ex helmReleaseAdapter) export() interface{} {
return exportHelmRelease(ex.HelmRelease)
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
func (ex helmReleaseListAdapter) exportItem(i int) interface{} {
return exportHelmRelease(&ex.HelmReleaseList.Items[i])
}

@ -17,17 +17,9 @@ limitations under the License.
package main
import (
"context"
"fmt"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
"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"
"github.com/fluxcd/flux2/internal/utils"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
)
var exportKsCmd = &cobra.Command{
@ -41,60 +33,17 @@ var exportKsCmd = &cobra.Command{
# Export a Kustomization
flux export kustomization my-app > kustomization.yaml
`,
RunE: exportKsCmdRun,
RunE: exportCommand{
object: kustomizationAdapter{&kustomizev1.Kustomization{}},
list: kustomizationListAdapter{&kustomizev1.KustomizationList{}},
}.run,
}
func init() {
exportCmd.AddCommand(exportKsCmd)
}
func exportKsCmdRun(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("kustomization name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list kustomizev1.KustomizationList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no kustomizations found in %s namespace", rootArgs.namespace)
return nil
}
for _, kustomization := range list.Items {
if err := exportKs(kustomization); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var kustomization kustomizev1.Kustomization
err = kubeClient.Get(ctx, namespacedName, &kustomization)
if err != nil {
return err
}
return exportKs(kustomization)
}
return nil
}
func exportKs(kustomization kustomizev1.Kustomization) error {
func exportKs(kustomization *kustomizev1.Kustomization) interface{} {
gvk := kustomizev1.GroupVersion.WithKind("Kustomization")
export := kustomizev1.Kustomization{
TypeMeta: metav1.TypeMeta{
@ -110,12 +59,13 @@ func exportKs(kustomization kustomizev1.Kustomization) error {
Spec: kustomization.Spec,
}
data, err := yaml.Marshal(export)
if err != nil {
return err
}
return export
}
func (ex kustomizationAdapter) export() interface{} {
return exportKs(ex.Kustomization)
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
func (ex kustomizationListAdapter) exportItem(i int) interface{} {
return exportKs(&ex.KustomizationList.Items[i])
}

@ -17,17 +17,9 @@ limitations under the License.
package main
import (
"context"
"fmt"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"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"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
)
var exportReceiverCmd = &cobra.Command{
@ -40,60 +32,17 @@ var exportReceiverCmd = &cobra.Command{
# Export a Receiver
flux export receiver main > main.yaml
`,
RunE: exportReceiverCmdRun,
RunE: exportCommand{
list: receiverListAdapter{&notificationv1.ReceiverList{}},
object: receiverAdapter{&notificationv1.Receiver{}},
}.run,
}
func init() {
exportCmd.AddCommand(exportReceiverCmd)
}
func exportReceiverCmdRun(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list notificationv1.ReceiverList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no receivers found in %s namespace", rootArgs.namespace)
return nil
}
for _, receiver := range list.Items {
if err := exportReceiver(receiver); err != nil {
return err
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var receiver notificationv1.Receiver
err = kubeClient.Get(ctx, namespacedName, &receiver)
if err != nil {
return err
}
return exportReceiver(receiver)
}
return nil
}
func exportReceiver(receiver notificationv1.Receiver) error {
func exportReceiver(receiver *notificationv1.Receiver) interface{} {
gvk := notificationv1.GroupVersion.WithKind("Receiver")
export := notificationv1.Receiver{
TypeMeta: metav1.TypeMeta{
@ -109,12 +58,13 @@ func exportReceiver(receiver notificationv1.Receiver) error {
Spec: receiver.Spec,
}
data, err := yaml.Marshal(export)
if err != nil {
return err
}
return export
}
func (ex receiverAdapter) export() interface{} {
return exportReceiver(ex.Receiver)
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
func (ex receiverListAdapter) exportItem(i int) interface{} {
return exportReceiver(&ex.ReceiverList.Items[i])
}

@ -0,0 +1,133 @@
/*
Copyright 2021 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 (
"context"
"fmt"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// exportableWithSecret represents a type that you can fetch from the Kubernetes
// API, get a secretRef from the spec, then tidy up for serialising.
type exportableWithSecret interface {
adapter
exportable
secret() *types.NamespacedName
}
// exportableWithSecretList represents a type that has a list of values, each of
// which is exportableWithSecret.
type exportableWithSecretList interface {
listAdapter
exportableList
secretItem(i int) *types.NamespacedName
}
type exportWithSecretCommand struct {
apiType
object exportableWithSecret
list exportableWithSecretList
}
func (export exportWithSecretCommand) run(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
err = kubeClient.List(ctx, export.list.asClientList(), client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if export.list.len() == 0 {
return fmt.Errorf("no objects found in %s namespace", rootArgs.namespace)
}
for i := 0; i < export.list.len(); i++ {
if err = printExport(export.list.exportItem(i)); err != nil {
return err
}
if exportSourceWithCred {
if export.list.secretItem(i) != nil {
namespacedName := *export.list.secretItem(i)
return printSecretCredentials(ctx, kubeClient, namespacedName)
}
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
err = kubeClient.Get(ctx, namespacedName, export.object.asClientObject())
if err != nil {
return err
}
if err := printExport(export.object.export()); err != nil {
return err
}
if exportSourceWithCred {
if export.object.secret() != nil {
namespacedName := *export.object.secret()
return printSecretCredentials(ctx, kubeClient, namespacedName)
}
}
}
return nil
}
func printSecretCredentials(ctx context.Context, kubeClient client.Client, nsName types.NamespacedName) error {
var cred corev1.Secret
err := kubeClient.Get(ctx, nsName, &cred)
if err != nil {
return fmt.Errorf("failed to retrieve secret %s, error: %w", nsName.Name, err)
}
exported := corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: nsName.Name,
Namespace: nsName.Namespace,
},
Data: cred.Data,
Type: cred.Type,
}
return printExport(exported)
}

@ -17,18 +17,10 @@ limitations under the License.
package main
import (
"context"
"fmt"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
var exportSourceBucketCmd = &cobra.Command{
@ -41,70 +33,17 @@ var exportSourceBucketCmd = &cobra.Command{
# Export a Bucket source including the static credentials
flux export source bucket my-bucket --with-credentials > source.yaml
`,
RunE: exportSourceBucketCmdRun,
RunE: exportWithSecretCommand{
list: bucketListAdapter{&sourcev1.BucketList{}},
object: bucketAdapter{&sourcev1.Bucket{}},
}.run,
}
func init() {
exportSourceCmd.AddCommand(exportSourceBucketCmd)
}
func exportSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list sourcev1.BucketList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil
}
for _, bucket := range list.Items {
if err := exportBucket(bucket); err != nil {
return err
}
if exportSourceWithCred {
if err := exportBucketCredentials(ctx, kubeClient, bucket); err != nil {
return err
}
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var bucket sourcev1.Bucket
err = kubeClient.Get(ctx, namespacedName, &bucket)
if err != nil {
return err
}
if err := exportBucket(bucket); err != nil {
return err
}
if exportSourceWithCred {
return exportBucketCredentials(ctx, kubeClient, bucket)
}
}
return nil
}
func exportBucket(source sourcev1.Bucket) error {
func exportBucket(source *sourcev1.Bucket) interface{} {
gvk := sourcev1.GroupVersion.WithKind(sourcev1.BucketKind)
export := sourcev1.Bucket{
TypeMeta: metav1.TypeMeta{
@ -119,49 +58,34 @@ func exportBucket(source sourcev1.Bucket) error {
},
Spec: source.Spec,
}
data, err := yaml.Marshal(export)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
return export
}
func exportBucketCredentials(ctx context.Context, kubeClient client.Client, source sourcev1.Bucket) error {
func getBucketSecret(source *sourcev1.Bucket) *types.NamespacedName {
if source.Spec.SecretRef != nil {
namespacedName := types.NamespacedName{
Namespace: source.Namespace,
Name: source.Spec.SecretRef.Name,
}
var cred corev1.Secret
err := kubeClient.Get(ctx, namespacedName, &cred)
if err != nil {
return fmt.Errorf("failed to retrieve secret %s, error: %w", namespacedName.Name, err)
}
exported := corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
},
Data: cred.Data,
Type: cred.Type,
}
data, err := yaml.Marshal(exported)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return &namespacedName
}
return nil
}
func (ex bucketAdapter) secret() *types.NamespacedName {
return getBucketSecret(ex.Bucket)
}
func (ex bucketListAdapter) secretItem(i int) *types.NamespacedName {
return getBucketSecret(&ex.BucketList.Items[i])
}
func (ex bucketAdapter) export() interface{} {
return exportBucket(ex.Bucket)
}
func (ex bucketListAdapter) exportItem(i int) interface{} {
return exportBucket(&ex.BucketList.Items[i])
}

@ -17,18 +17,10 @@ limitations under the License.
package main
import (
"context"
"fmt"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
var exportSourceGitCmd = &cobra.Command{
@ -41,70 +33,17 @@ var exportSourceGitCmd = &cobra.Command{
# Export a GitRepository source including the SSH key pair or basic auth credentials
flux export source git my-private-repo --with-credentials > source.yaml
`,
RunE: exportSourceGitCmdRun,
RunE: exportWithSecretCommand{
object: gitRepositoryAdapter{&sourcev1.GitRepository{}},
list: gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
}.run,
}
func init() {
exportSourceCmd.AddCommand(exportSourceGitCmd)
}
func exportSourceGitCmdRun(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list sourcev1.GitRepositoryList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil
}
for _, repository := range list.Items {
if err := exportGit(repository); err != nil {
return err
}
if exportSourceWithCred {
if err := exportGitCredentials(ctx, kubeClient, repository); err != nil {
return err
}
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var repository sourcev1.GitRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
if err := exportGit(repository); err != nil {
return err
}
if exportSourceWithCred {
return exportGitCredentials(ctx, kubeClient, repository)
}
}
return nil
}
func exportGit(source sourcev1.GitRepository) error {
func exportGit(source *sourcev1.GitRepository) interface{} {
gvk := sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)
export := sourcev1.GitRepository{
TypeMeta: metav1.TypeMeta{
@ -120,48 +59,33 @@ func exportGit(source sourcev1.GitRepository) error {
Spec: source.Spec,
}
data, err := yaml.Marshal(export)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
return export
}
func exportGitCredentials(ctx context.Context, kubeClient client.Client, source sourcev1.GitRepository) error {
func getGitSecret(source *sourcev1.GitRepository) *types.NamespacedName {
if source.Spec.SecretRef != nil {
namespacedName := types.NamespacedName{
Namespace: source.Namespace,
Name: source.Spec.SecretRef.Name,
}
var cred corev1.Secret
err := kubeClient.Get(ctx, namespacedName, &cred)
if err != nil {
return fmt.Errorf("failed to retrieve secret %s, error: %w", namespacedName.Name, err)
}
return &namespacedName
}
exported := corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
},
Data: cred.Data,
Type: cred.Type,
}
return nil
}
data, err := yaml.Marshal(exported)
if err != nil {
return err
}
func (ex gitRepositoryAdapter) secret() *types.NamespacedName {
return getGitSecret(ex.GitRepository)
}
fmt.Println("---")
fmt.Println(resourceToString(data))
}
return nil
func (ex gitRepositoryListAdapter) secretItem(i int) *types.NamespacedName {
return getGitSecret(&ex.GitRepositoryList.Items[i])
}
func (ex gitRepositoryAdapter) export() interface{} {
return exportGit(ex.GitRepository)
}
func (ex gitRepositoryListAdapter) exportItem(i int) interface{} {
return exportGit(&ex.GitRepositoryList.Items[i])
}

@ -17,18 +17,10 @@ limitations under the License.
package main
import (
"context"
"fmt"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/internal/utils"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
var exportSourceHelmCmd = &cobra.Command{
@ -41,70 +33,17 @@ var exportSourceHelmCmd = &cobra.Command{
# Export a HelmRepository source including the basic auth credentials
flux export source helm my-private-repo --with-credentials > source.yaml
`,
RunE: exportSourceHelmCmdRun,
RunE: exportWithSecretCommand{
list: helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
object: helmRepositoryAdapter{&sourcev1.HelmRepository{}},
}.run,
}
func init() {
exportSourceCmd.AddCommand(exportSourceHelmCmd)
}
func exportSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
if !exportArgs.all && len(args) < 1 {
return fmt.Errorf("name is required")
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
if exportArgs.all {
var list sourcev1.HelmRepositoryList
err = kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace))
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no source found in %s namespace", rootArgs.namespace)
return nil
}
for _, repository := range list.Items {
if err := exportHelmRepository(repository); err != nil {
return err
}
if exportSourceWithCred {
if err := exportHelmCredentials(ctx, kubeClient, repository); err != nil {
return err
}
}
}
} else {
name := args[0]
namespacedName := types.NamespacedName{
Namespace: rootArgs.namespace,
Name: name,
}
var repository sourcev1.HelmRepository
err = kubeClient.Get(ctx, namespacedName, &repository)
if err != nil {
return err
}
if err := exportHelmRepository(repository); err != nil {
return err
}
if exportSourceWithCred {
return exportHelmCredentials(ctx, kubeClient, repository)
}
}
return nil
}
func exportHelmRepository(source sourcev1.HelmRepository) error {
func exportHelmRepository(source *sourcev1.HelmRepository) interface{} {
gvk := sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)
export := sourcev1.HelmRepository{
TypeMeta: metav1.TypeMeta{
@ -119,49 +58,32 @@ func exportHelmRepository(source sourcev1.HelmRepository) error {
},
Spec: source.Spec,
}
data, err := yaml.Marshal(export)
if err != nil {
return err
}
fmt.Println("---")
fmt.Println(resourceToString(data))
return nil
return export
}
func exportHelmCredentials(ctx context.Context, kubeClient client.Client, source sourcev1.HelmRepository) error {
func getHelmSecret(source *sourcev1.HelmRepository) *types.NamespacedName {
if source.Spec.SecretRef != nil {
namespacedName := types.NamespacedName{
Namespace: source.Namespace,
Name: source.Spec.SecretRef.Name,
}
var cred corev1.Secret
err := kubeClient.Get(ctx, namespacedName, &cred)
if err != nil {
return fmt.Errorf("failed to retrieve secret %s, error: %w", namespacedName.Name, err)
}
return &namespacedName
}
return nil
}
exported := corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: namespacedName.Name,
Namespace: namespacedName.Namespace,
},
Data: cred.Data,
Type: cred.Type,
}
func (ex helmRepositoryAdapter) secret() *types.NamespacedName {
return getHelmSecret(ex.HelmRepository)
}
data, err := yaml.Marshal(exported)
if err != nil {
return err
}
func (ex helmRepositoryListAdapter) secretItem(i int) *types.NamespacedName {
return getHelmSecret(&ex.HelmRepositoryList.Items[i])
}
fmt.Println("---")
fmt.Println(resourceToString(data))
}
return nil
func (ex helmRepositoryAdapter) export() interface{} {
return exportHelmRepository(ex.HelmRepository)
}
func (ex helmRepositoryListAdapter) exportItem(i int) interface{} {
return exportHelmRepository(&ex.HelmRepositoryList.Items[i])
}

@ -17,19 +17,11 @@ limitations under the License.
package main
import (
"context"
"os"
"strconv"
"strings"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
)
var getAlertCmd = &cobra.Command{
@ -40,64 +32,26 @@ var getAlertCmd = &cobra.Command{
Example: ` # List all Alerts and their status
flux get alerts
`,
RunE: getAlertCmdRun,
RunE: getCommand{
apiType: alertType,
list: &alertListAdapter{&notificationv1.AlertList{}},
}.run,
}
func init() {
getCmd.AddCommand(getAlertCmd)
}
func getAlertCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
var listOpts []client.ListOption
if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
}
var list notificationv1.AlertList
err = kubeClient.List(ctx, &list, listOpts...)
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no alerts found in %s namespace", rootArgs.namespace)
return nil
}
func (s alertListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string {
item := s.Items[i]
status, msg := statusAndMessage(item.Status.Conditions)
return append(nameColumns(&item, includeNamespace, includeKind), status, msg, strings.Title(strconv.FormatBool(item.Spec.Suspend)))
}
header := []string{"Name", "Ready", "Message", "Suspended"}
if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, alert := range list.Items {
row := []string{}
if c := apimeta.FindStatusCondition(alert.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
alert.GetName(),
string(c.Status),
c.Message,
strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
}
} else {
row = []string{
alert.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
strings.Title(strconv.FormatBool(alert.Spec.Suspend)),
}
}
if getArgs.allNamespaces {
row = append([]string{alert.Namespace}, row...)
}
rows = append(rows, row)
func (s alertListAdapter) headers(includeNamespace bool) []string {
headers := []string{"Name", "Ready", "Message", "Suspended"}
if includeNamespace {
return append(namespaceHeader, headers...)
}
utils.PrintTable(os.Stdout, header, rows)
return nil
return headers
}

@ -17,17 +17,8 @@ limitations under the License.
package main
import (
"context"
"os"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
)
var getAlertProviderCmd = &cobra.Command{
@ -38,62 +29,26 @@ var getAlertProviderCmd = &cobra.Command{
Example: ` # List all Providers and their status
flux get alert-providers
`,
RunE: getAlertProviderCmdRun,
RunE: getCommand{
apiType: alertProviderType,
list: alertProviderListAdapter{&notificationv1.ProviderList{}},
}.run,
}
func init() {
getCmd.AddCommand(getAlertProviderCmd)
}
func getAlertProviderCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
var listOpts []client.ListOption
if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
}
var list notificationv1.ProviderList
err = kubeClient.List(ctx, &list, listOpts...)
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no providers found in %s namespace", rootArgs.namespace)
return nil
}
func (s alertProviderListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string {
item := s.Items[i]
status, msg := statusAndMessage(item.Status.Conditions)
return append(nameColumns(&item, includeNamespace, includeKind), status, msg)
}
header := []string{"Name", "Ready", "Message"}
if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, provider := range list.Items {
row := []string{}
if c := apimeta.FindStatusCondition(provider.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
provider.GetName(),
string(c.Status),
c.Message,
}
} else {
row = []string{
provider.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
}
}
if getArgs.allNamespaces {
row = append([]string{provider.Namespace}, row...)
}
rows = append(rows, row)
func (s alertProviderListAdapter) headers(includeNamespace bool) []string {
headers := []string{"Name", "Ready", "Message"}
if includeNamespace {
return append(namespaceHeader, headers...)
}
utils.PrintTable(os.Stdout, header, rows)
return nil
return headers
}

@ -17,19 +17,11 @@ limitations under the License.
package main
import (
"context"
"os"
"strconv"
"strings"
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/flux2/internal/utils"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra"
)
var getReceiverCmd = &cobra.Command{
@ -40,61 +32,26 @@ var getReceiverCmd = &cobra.Command{
Example: ` # List all Receiver and their status
flux get receivers
`,
RunE: getReceiverCmdRun,
RunE: getCommand{
apiType: receiverType,
list: receiverListAdapter{&notificationv1.ReceiverList{}},
}.run,
}
func init() {
getCmd.AddCommand(getReceiverCmd)
}
func getReceiverCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
var listOpts []client.ListOption
if !getArgs.allNamespaces {
listOpts = append(listOpts, client.InNamespace(rootArgs.namespace))
}
var list notificationv1.ReceiverList
err = kubeClient.List(ctx, &list, listOpts...)
if err != nil {
return err
}
if len(list.Items) == 0 {
logger.Failuref("no receivers found in %s namespace", rootArgs.namespace)
return nil
}
func (s receiverListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string {
item := s.Items[i]
status, msg := statusAndMessage(item.Status.Conditions)
return append(nameColumns(&item, includeNamespace, includeKind), status, msg, strings.Title(strconv.FormatBool(item.Spec.Suspend)))
}
header := []string{"Name", "Ready", "Message", "Suspended"}
if getArgs.allNamespaces {
header = append([]string{"Namespace"}, header...)
}
var rows [][]string
for _, receiver := range list.Items {
var row []string
if c := apimeta.FindStatusCondition(receiver.Status.Conditions, meta.ReadyCondition); c != nil {
row = []string{
receiver.GetName(),
string(c.Status),
c.Message,
strings.Title(strconv.FormatBool(receiver.Spec.Suspend)),
}
} else {
row = []string{
receiver.GetName(),
string(metav1.ConditionFalse),
"waiting to be reconciled",
strings.Title(strconv.FormatBool(receiver.Spec.Suspend)),
}
}
rows = append(rows, row)
func (s receiverListAdapter) headers(includeNamespace bool) []string {
headers := []string{"Name", "Ready", "Message", "Suspended"}
if includeNamespace {
return append(namespaceHeader, headers...)
}
utils.PrintTable(os.Stdout, header, rows)
return nil
return headers
}

@ -0,0 +1,51 @@
/*
Copyright 2021 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 (
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
// notificationv1.Receiver
var receiverType = apiType{
kind: notificationv1.ReceiverKind,
humanKind: "receiver",
}
type receiverAdapter struct {
*notificationv1.Receiver
}
func (a receiverAdapter) asClientObject() client.Object {
return a.Receiver
}
// notificationv1.Receiver
type receiverListAdapter struct {
*notificationv1.ReceiverList
}
func (a receiverListAdapter) asClientList() client.ObjectList {
return a.ReceiverList
}
func (a receiverListAdapter) len() int {
return len(a.ReceiverList.Items)
}
Loading…
Cancel
Save