backup works
This commit is contained in:
parent
4c300253c4
commit
aa640afff2
@ -27,10 +27,12 @@ WORKDIR /dist
|
|||||||
RUN cp /build/formolcli .
|
RUN cp /build/formolcli .
|
||||||
|
|
||||||
# Build a small image
|
# Build a small image
|
||||||
FROM scratch
|
FROM arm32v7/alpine:3.12
|
||||||
|
|
||||||
COPY --from=builder /dist/formolcli /
|
RUN apk add --no-cache restic
|
||||||
|
COPY bin/restic /usr/local/bin
|
||||||
|
COPY --from=builder /dist/formolcli /usr/local/bin
|
||||||
|
|
||||||
# Command to run
|
# Command to run
|
||||||
ENTRYPOINT ["/formolcli"]
|
ENTRYPOINT ["/usr/local/bin/formolcli"]
|
||||||
CMD ["--help"]
|
CMD ["--help"]
|
||||||
|
|||||||
BIN
bin/restic
Executable file
BIN
bin/restic
Executable file
Binary file not shown.
@ -13,6 +13,17 @@ metadata:
|
|||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: backup-listener
|
||||||
|
labels:
|
||||||
|
app: backup-listener
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["formol.desmojim.fr"]
|
||||||
|
resources: ["backupsessions", "backupconfigurations"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: backupsession-creator
|
name: backupsession-creator
|
||||||
labels:
|
labels:
|
||||||
@ -37,3 +48,19 @@ subjects:
|
|||||||
namespace: backup
|
namespace: backup
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: backup-listener
|
||||||
|
labels:
|
||||||
|
app: backup-listener
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: backup-listener
|
||||||
|
subjects:
|
||||||
|
- name: default
|
||||||
|
namespace: default
|
||||||
|
kind: ServiceAccount
|
||||||
|
|
||||||
|
|||||||
61
src/backup/root.go
Normal file
61
src/backup/root.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package backup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
repository string
|
||||||
|
passwordFile string
|
||||||
|
aws_access_key_id string
|
||||||
|
aws_secret_access_key string
|
||||||
|
resticExec = "/usr/local/bin/restic"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if repository = os.Getenv("RESTIC_REPOSITORY"); repository == "" {
|
||||||
|
log.Fatal("RESTIC_REPOSITORY not set")
|
||||||
|
}
|
||||||
|
if passwordFile = os.Getenv("RESTIC_PASSWORD"); passwordFile == "" {
|
||||||
|
log.Fatal("RESTIC_PASSWORD not set")
|
||||||
|
}
|
||||||
|
if aws_access_key_id = os.Getenv("AWS_ACCESS_KEY_ID"); aws_access_key_id == "" {
|
||||||
|
log.Fatal("AWS_ACCESS_KEY_ID not set")
|
||||||
|
}
|
||||||
|
if aws_secret_access_key = os.Getenv("AWS_SECRET_ACCESS_KEY"); aws_secret_access_key == "" {
|
||||||
|
log.Fatal("AWS_SECRET_ACCESS_KEY not set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkRepo(repo string) error {
|
||||||
|
cmd := exec.Command(resticExec, "check", "-r", repo)
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
cmd = exec.Command(resticExec, "init", "-r", repo)
|
||||||
|
err = cmd.Run()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func BackupVolume(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func BackupDeployment(prefix string, paths []string) error {
|
||||||
|
newrepo := repository
|
||||||
|
if prefix != "" {
|
||||||
|
newrepo = repository + "/" + prefix
|
||||||
|
}
|
||||||
|
if err := checkRepo(newrepo); err != nil {
|
||||||
|
log.Fatal("unable to setup newrepo", "newrepo", newrepo)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd := exec.Command(resticExec, "backup", "-r", newrepo, strings.Join(paths, " "))
|
||||||
|
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
51
src/cmd/backup.go
Normal file
51
src/cmd/backup.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
|
||||||
|
|
||||||
|
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 cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// backupCmd represents the backup command
|
||||||
|
var backupCmd = &cobra.Command{
|
||||||
|
Use: "backup",
|
||||||
|
Short: "A brief description of your command",
|
||||||
|
Long: `A longer description that spans multiple lines and likely contains examples
|
||||||
|
and usage of using your command. For example:
|
||||||
|
|
||||||
|
Cobra is a CLI library for Go that empowers applications.
|
||||||
|
This application is a tool to generate the needed files
|
||||||
|
to quickly create a Cobra application.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("backup called")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(backupCmd)
|
||||||
|
|
||||||
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
// Cobra supports Persistent Flags which will work for this command
|
||||||
|
// and all subcommands, e.g.:
|
||||||
|
// backupCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||||
|
|
||||||
|
// Cobra supports local flags which will only run when this command
|
||||||
|
// is called directly, e.g.:
|
||||||
|
// backupCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||||
|
}
|
||||||
53
src/cmd/server.go
Normal file
53
src/cmd/server.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
|
||||||
|
|
||||||
|
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 cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/desmo999r/formolcli/create"
|
||||||
|
)
|
||||||
|
|
||||||
|
// serverCmd represents the server command
|
||||||
|
var serverCmd = &cobra.Command{
|
||||||
|
Use: "server",
|
||||||
|
Short: "A brief description of your command",
|
||||||
|
Long: `A longer description that spans multiple lines and likely contains examples
|
||||||
|
and usage of using your command. For example:
|
||||||
|
|
||||||
|
Cobra is a CLI library for Go that empowers applications.
|
||||||
|
This application is a tool to generate the needed files
|
||||||
|
to quickly create a Cobra application.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("server called")
|
||||||
|
create.Server()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
createCmd.AddCommand(serverCmd)
|
||||||
|
|
||||||
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
// Cobra supports Persistent Flags which will work for this command
|
||||||
|
// and all subcommands, e.g.:
|
||||||
|
// serverCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||||
|
|
||||||
|
// Cobra supports local flags which will only run when this command
|
||||||
|
// is called directly, e.g.:
|
||||||
|
// serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||||
|
}
|
||||||
56
src/cmd/volume.go
Normal file
56
src/cmd/volume.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
|
||||||
|
|
||||||
|
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 cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/desmo999r/formolcli/backup"
|
||||||
|
)
|
||||||
|
|
||||||
|
// pvcCmd represents the pvc command
|
||||||
|
var volumeCmd = &cobra.Command{
|
||||||
|
Use: "volume",
|
||||||
|
Short: "A brief description of your command",
|
||||||
|
Long: `A longer description that spans multiple lines and likely contains examples
|
||||||
|
and usage of using your command. For example:
|
||||||
|
|
||||||
|
Cobra is a CLI library for Go that empowers applications.
|
||||||
|
This application is a tool to generate the needed files
|
||||||
|
to quickly create a Cobra application.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("volume called")
|
||||||
|
path, _ := cmd.Flags().GetString("path")
|
||||||
|
_ = backup.BackupVolume(path)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
backupCmd.AddCommand(volumeCmd)
|
||||||
|
|
||||||
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
// Cobra supports Persistent Flags which will work for this command
|
||||||
|
// and all subcommands, e.g.:
|
||||||
|
// pvcCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||||
|
|
||||||
|
// Cobra supports local flags which will only run when this command
|
||||||
|
// is called directly, e.g.:
|
||||||
|
// pvcCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||||
|
volumeCmd.Flags().String("path", "", "Path to the data to backup")
|
||||||
|
volumeCmd.MarkFlagRequired("path")
|
||||||
|
}
|
||||||
113
src/controllers/backupsession_controller.go
Normal file
113
src/controllers/backupsession_controller.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
"github.com/desmo999r/formolcli/backup"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
deploymentName = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
namespace := os.Getenv("POD_NAMESPACE")
|
||||||
|
if namespace == "" {
|
||||||
|
panic("No POD_NAMESPACE env var")
|
||||||
|
}
|
||||||
|
config, err := rest.InClusterConfig()
|
||||||
|
if err != nil {
|
||||||
|
config, err = clientcmd.BuildConfigFromFlags("", filepath.Join(os.Getenv("HOME"), ".kube", "config",))
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clientset, err := kubernetes.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
panic("unable to get clientset")
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname := os.Getenv("POD_NAME")
|
||||||
|
if hostname == "" {
|
||||||
|
panic("unable to get hostname")
|
||||||
|
}
|
||||||
|
|
||||||
|
pod, err := clientset.CoreV1().Pods(namespace).Get(hostname, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
panic("unable to get pod")
|
||||||
|
}
|
||||||
|
|
||||||
|
podOwner := metav1.GetControllerOf(pod)
|
||||||
|
replicasetList, err := clientset.AppsV1().ReplicaSets(namespace).List(metav1.ListOptions{
|
||||||
|
FieldSelector: "metadata.name=" + string(podOwner.Name),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic("unable to get replicaset" + err.Error())
|
||||||
|
}
|
||||||
|
for _, replicaset := range replicasetList.Items {
|
||||||
|
replicasetOwner := metav1.GetControllerOf(&replicaset)
|
||||||
|
deploymentName = replicasetOwner.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BackupSessionReconciler reconciles a BackupSession object
|
||||||
|
type BackupSessionReconciler struct {
|
||||||
|
client.Client
|
||||||
|
Log logr.Logger
|
||||||
|
Scheme *runtime.Scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *BackupSessionReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
log := r.Log.WithValues("backupsession", req.NamespacedName)
|
||||||
|
|
||||||
|
// your logic here
|
||||||
|
backupSession := &formolv1alpha1.BackupSession{}
|
||||||
|
if err := r.Get(ctx, req.NamespacedName, backupSession); err != nil {
|
||||||
|
log.Error(err, "unable to get backupsession")
|
||||||
|
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.V(1).Info("backupSession.Namespace", "namespace", backupSession.Namespace)
|
||||||
|
log.V(1).Info("backupSession.Spec.Ref.Name", "name", backupSession.Spec.Ref.Name)
|
||||||
|
backupConf := &formolv1alpha1.BackupConfiguration{}
|
||||||
|
if err := r.Get(ctx, client.ObjectKey{
|
||||||
|
Namespace: backupSession.Namespace,
|
||||||
|
Name: backupSession.Spec.Ref.Name,
|
||||||
|
}, backupConf); err != nil {
|
||||||
|
log.Error(err, "unable to get backupConfiguration")
|
||||||
|
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.V(1).Info("Found BackupConfiguration", "BackupConfiguration", backupConf)
|
||||||
|
|
||||||
|
// Found the BackupConfiguration.
|
||||||
|
switch backupConf.Spec.Target.Kind {
|
||||||
|
case "Deployment":
|
||||||
|
if err := backup.BackupDeployment("", backupConf.Spec.Paths); err != nil {
|
||||||
|
log.Error(err, "unable to backup deployment")
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *BackupSessionReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
|
For(&formolv1alpha1.BackupSession{}).
|
||||||
|
Complete(r)
|
||||||
|
}
|
||||||
|
|
||||||
@ -39,7 +39,6 @@ func CreateBackupSession(name string, namespace string) {
|
|||||||
Spec: formolv1alpha1.BackupSessionSpec{
|
Spec: formolv1alpha1.BackupSessionSpec{
|
||||||
Ref: formolv1alpha1.Ref{
|
Ref: formolv1alpha1.Ref{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: namespace,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Status: formolv1alpha1.BackupSessionStatus{},
|
Status: formolv1alpha1.BackupSessionStatus{},
|
||||||
|
|||||||
62
src/create/server.go
Normal file
62
src/create/server.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package create
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"flag"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||||
|
"github.com/desmo999r/formolcli/controllers"
|
||||||
|
formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
scheme = runtime.NewScheme()
|
||||||
|
setupLog = ctrl.Log.WithName("server")
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_ = clientgoscheme.AddToScheme(scheme)
|
||||||
|
_ = formolv1alpha1.AddToScheme(scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Server(){
|
||||||
|
var metricsAddr string
|
||||||
|
var enableLeaderElection bool
|
||||||
|
flag.StringVar(&metricsAddr, "metrics-addr", ":8082", "The address the metric endpoint binds to.")
|
||||||
|
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
|
||||||
|
"Enable leader election for controller manager. "+
|
||||||
|
"Enabling this will ensure there is only one active controller manager.")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
|
||||||
|
|
||||||
|
config, err := ctrl.GetConfig()
|
||||||
|
mgr, err := ctrl.NewManager(config, ctrl.Options{
|
||||||
|
Scheme: scheme,
|
||||||
|
MetricsBindAddress: metricsAddr,
|
||||||
|
Port: 9443,
|
||||||
|
LeaderElection: enableLeaderElection,
|
||||||
|
LeaderElectionID: "12345.desmojim.fr",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
setupLog.Error(err, "unable to create manager")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = (&controllers.BackupSessionReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Log: ctrl.Log.WithName("controllers").WithName("BackupSession"),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "BackupSession")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
setupLog.Info("starting manager")
|
||||||
|
if err = mgr.Start(ctrl.SetupSignalHandler()); err != nil {
|
||||||
|
setupLog.Error(err, "problem running the manager")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/go.mod
16
src/go.mod
@ -3,11 +3,15 @@ module github.com/desmo999r/formolcli
|
|||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/desmo999r/formol v0.0.0-20201125193419-7fbf7274cbde
|
github.com/desmo999r/formol v0.1.4
|
||||||
|
github.com/go-logr/logr v0.1.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/spf13/cobra v1.1.1
|
github.com/onsi/ginkgo v1.11.0
|
||||||
github.com/spf13/viper v1.7.1
|
github.com/onsi/gomega v1.8.1
|
||||||
k8s.io/apimachinery v0.18.6
|
github.com/spf13/cobra v0.0.5
|
||||||
k8s.io/client-go v0.18.6
|
github.com/spf13/viper v1.3.2
|
||||||
sigs.k8s.io/controller-runtime v0.6.4
|
k8s.io/api v0.17.2
|
||||||
|
k8s.io/apimachinery v0.17.2
|
||||||
|
k8s.io/client-go v0.17.2
|
||||||
|
sigs.k8s.io/controller-runtime v0.5.0
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user