Move kubernetes configuration into settings

This should make it easier to use the fake client for testing
This commit is contained in:
Ian Howell 2019-05-21 12:43:03 -05:00
parent 3ea070bcd5
commit 039224b6fe
6 changed files with 58 additions and 94 deletions

View File

@ -11,18 +11,15 @@ import (
"github.com/ian-howell/airshipctl/pkg/log"
)
// NewRootCmd creates the root `airshipctl` command. All other commands are
// subcommands branching from this one
func NewRootCmd(out io.Writer, args []string) (*cobra.Command, error) {
func NewRootCmd(out io.Writer, settings *environment.AirshipCTLSettings, args []string) (*cobra.Command, error) {
rootCmd := &cobra.Command{
Use: "airshipctl",
Short: "airshipctl is a unified entrypoint to various airship components",
}
rootCmd.SetOutput(out)
// Settings flags - This section should probably be moved to pkg/environment
settings := &environment.AirshipCTLSettings{}
settings.InitFlags(rootCmd)
rootCmd.AddCommand(NewVersionCommand(out))
@ -31,15 +28,15 @@ func NewRootCmd(out io.Writer, args []string) (*cobra.Command, error) {
rootCmd.PersistentFlags().Parse(args)
settings.InitDefaults()
log.Init(settings, out)
return rootCmd, nil
}
// Execute runs the base airshipctl command
func Execute(out io.Writer) {
rootCmd, err := NewRootCmd(out, os.Args[1:])
rootCmd, err := NewRootCmd(out, &environment.AirshipCTLSettings{}, os.Args[1:])
if err != nil {
fmt.Fprintln(out, err)
os.Exit(1)

View File

@ -5,16 +5,15 @@ import (
"io"
"github.com/spf13/cobra"
v1beta2 "k8s.io/api/apps/v1beta2"
v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apixv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apixv1beta1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
v1beta2 "k8s.io/api/apps/v1beta2"
"k8s.io/apimachinery/pkg/api/errors"
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/ian-howell/airshipctl/pkg/environment"
)
@ -30,37 +29,22 @@ var (
type workflowInitCmd struct {
out io.Writer
config *rest.Config
kubeclient *kubernetes.Clientset
kubeclient kubernetes.Interface
}
// NewWorkflowInitCommand is a command for bootstrapping a kubernetes cluster with the necessary components for Argo workflows
func NewWorkflowInitCommand(out io.Writer, settings *environment.AirshipCTLSettings, args []string) *cobra.Command {
workflowInit := &workflowInitCmd{
out: out,
out: out,
config: settings.KubeConfig,
kubeclient: settings.KubeClient,
}
workflowInitCommand := &cobra.Command{
Use: "init [flags]",
Short: "bootstraps the kubernetes cluster with the Workflow CRDs and controller",
Run: func(cmd *cobra.Command, args []string) {
if settings.KubeConfigFilePath == "" {
settings.KubeConfigFilePath = clientcmd.RecommendedHomeFile
}
config, err := clientcmd.BuildConfigFromFlags("", settings.KubeConfigFilePath)
if err != nil {
fmt.Fprintf(out, "Could not create kubernetes config: %s\n", err.Error())
return
}
workflowInit.config = config
kubeclient, err := kubernetes.NewForConfig(config)
if err != nil {
fmt.Fprintf(out, "Could not create kubernetes clientset: %s\n", err.Error())
return
}
workflowInit.kubeclient = kubeclient
fmt.Fprintf(out, "Creating namespace \"%s\"\n", argoNamespace)
_, err = kubeclient.CoreV1().Namespaces().Create(&v1.Namespace{
_, err := workflowInit.kubeclient.CoreV1().Namespaces().Create(&v1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: "argo"},
})
if err != nil {
@ -383,13 +367,13 @@ func (wfInit *workflowInitCmd) createArgoClusterRoleBinding() error {
ObjectMeta: metav1.ObjectMeta{Name: "argo-binding"},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: "argo-cluster-role",
Kind: "ClusterRole",
Name: "argo-cluster-role",
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: "argo",
Kind: "ServiceAccount",
Name: "argo",
Namespace: argoNamespace,
},
},
@ -401,7 +385,7 @@ func (wfInit *workflowInitCmd) createArgoClusterRoleBinding() error {
func (wfInit *workflowInitCmd) createArgoConfigMap() error {
_, err := wfInit.kubeclient.CoreV1().ConfigMaps(argoNamespace).Create(&v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "workflow-controller-configmap",
Name: "workflow-controller-configmap",
Namespace: argoNamespace,
},
})
@ -411,7 +395,7 @@ func (wfInit *workflowInitCmd) createArgoConfigMap() error {
func (wfInit *workflowInitCmd) createArgoDeployment() error {
_, err := wfInit.kubeclient.AppsV1beta2().Deployments(argoNamespace).Create(&v1beta2.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "workflow-controller",
Name: "workflow-controller",
Namespace: argoNamespace,
},
Spec: v1beta2.DeploymentSpec{
@ -436,10 +420,10 @@ func (wfInit *workflowInitCmd) createArgoDeployment() error {
"--configmap",
"workflow-controller-configmap",
"--executor-image",
"argoproj/argoexec:v2.2.1", // TODO(howell): Remove this hardcoded value
"argoproj/argoexec:v2.2.1", // TODO(howell): Remove this hardcoded value
},
Image: "argoproj/argoexec:v2.2.1", // TODO(howell): Remove this hardcoded value
Name: "workflow-controller",
Image: "argoproj/argoexec:v2.2.1", // TODO(howell): Remove this hardcoded value
Name: "workflow-controller",
},
},
ServiceAccountName: "argo",

View File

@ -8,7 +8,6 @@ import (
"github.com/argoproj/argo/pkg/client/clientset/versioned/typed/workflow/v1alpha1"
"github.com/spf13/cobra"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/clientcmd"
"github.com/ian-howell/airshipctl/pkg/environment"
)
@ -20,15 +19,7 @@ func NewWorkflowListCommand(out io.Writer, settings *environment.AirshipCTLSetti
Short: "list workflows",
Aliases: []string{"ls"},
Run: func(cmd *cobra.Command, args []string) {
if settings.KubeConfigFilePath == "" {
settings.KubeConfigFilePath = clientcmd.RecommendedHomeFile
}
config, err := clientcmd.BuildConfigFromFlags("", settings.KubeConfigFilePath)
if err != nil {
panic(err.Error())
}
clientSet, err := v1alpha1.NewForConfig(config)
clientSet, err := v1alpha1.NewForConfig(settings.KubeConfig)
if err != nil {
panic(err.Error())
}

10
go.sum
View File

@ -22,8 +22,10 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfc
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 h1:w3NnFcKR5241cfmQU5ZZAsf0xcpId6mWOupTvJlUX2U=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
@ -33,6 +35,7 @@ github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550 h1:mV9jbLoSW/8m
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4 h1:bRzFpEzvausOAt4va+I/22BZ1vXDtERngp0BNYDKej0=
github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@ -68,10 +71,12 @@ github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e h1:JHB7F/4TJCrYBW8+GZO8VkWDj1jxcWuCl6uxKODiyi4=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -84,10 +89,12 @@ github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhp
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@ -218,6 +225,7 @@ gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20150622162204-20b71e5b60d7/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84 h1:ELQJ5WuT+ydETLCpWvAuw8iGBQRGoJq+A3RAbbAcZUY=
gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
@ -231,10 +239,12 @@ k8s.io/apiextensions-apiserver v0.0.0-20190515024537-2fd0e9006049 h1:nVYyNZl5lEe
k8s.io/apiextensions-apiserver v0.0.0-20190515024537-2fd0e9006049/go.mod h1:yMQkVi5Qu0vmH4rNmnVu6v5kf1GnPj8+6TJG+he4+kw=
k8s.io/apimachinery v0.0.0-20190515023456-b74e4c97951f h1:cBrF1gFrJrvimOHZzyEHrvtlfqPV+KM7QZt3M0mepEg=
k8s.io/apimachinery v0.0.0-20190515023456-b74e4c97951f/go.mod h1:Ew3b/24/JSgJdn4RsnrLskv3LvMZDlZ1Fl1xopsJftY=
k8s.io/apiserver v0.0.0-20190515024203-a3c8296cef8c h1:JGoLJ099gxINHqgaFsMe+r2jM0fUOoz0GFPehb8QhGc=
k8s.io/apiserver v0.0.0-20190515024203-a3c8296cef8c/go.mod h1:c9qwKQexUHQq1ALDC7vAgSXOVXAFkGil5ZQWdqr3RhI=
k8s.io/client-go v0.0.0-20190515023709-78e94f51a042 h1:CkYQkY7TSQK/rDLm8Bit9fvvJJl3p1C5Dk+swSRz1m0=
k8s.io/client-go v0.0.0-20190515023709-78e94f51a042/go.mod h1:Ucfy225uJpWBtWGDwTtqUZmmgR/AzYM0vge2iB/bTQ4=
k8s.io/code-generator v0.0.0-20190511023357-639c964206c2/go.mod h1:YMQ7Lt97nW/I6nHACDccgS/sPAyrHQNans96RwPaSb8=
k8s.io/component-base v0.0.0-20190515024022-2354f2393ad4 h1:TOebDR8jh/AcqOEWnotJ+DYVUNcMA1GT86TR4Bg70KQ=
k8s.io/component-base v0.0.0-20190515024022-2354f2393ad4/go.mod h1:pKRi1i5IQdJDpK1LItot8oy27Bc3zL/hQiy9T171rvE=
k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE=

View File

@ -1,9 +1,10 @@
package environment
import (
restclient "k8s.io/client-go/rest"
"github.com/spf13/cobra"
"k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
// AirshipCTLSettings is a container for all of the settings needed by airshipctl
@ -17,6 +18,9 @@ type AirshipCTLSettings struct {
// with the cluster
KubeConfig *restclient.Config
// KubeClient contains a kubernetes clientset
KubeClient kubernetes.Interface
// Namespace is the kubernetes namespace to be used during the context of this action
Namespace string
@ -31,3 +35,26 @@ func (a *AirshipCTLSettings) InitFlags(cmd *cobra.Command) {
flags.StringVar(&a.KubeConfigFilePath, "kubeconfig", "", "path to kubeconfig")
flags.StringVar(&a.Namespace, "namespace", "default", "kubernetes namespace to use for the context of this command")
}
// InitDefaults assigns default values for any value that has not been previously set
func (a *AirshipCTLSettings) InitDefaults() error {
if a.KubeConfigFilePath == "" {
a.KubeConfigFilePath = clientcmd.RecommendedHomeFile
}
var err error
if a.KubeConfig == nil {
a.KubeConfig, err = clientcmd.BuildConfigFromFlags("", a.KubeConfigFilePath)
if err != nil {
return err
}
}
if a.KubeClient == nil {
a.KubeClient, err = kubernetes.NewForConfig(a.KubeConfig)
if err != nil {
return err
}
}
return nil
}

View File

@ -1,45 +0,0 @@
package kube
import (
"errors"
"os"
"path/filepath"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"github.com/ian-howell/airshipctl/pkg/util"
)
// Client is a device which communicates with the Kubernetes API
type Client struct {
kubernetes.Interface
}
// NewForConfig creates a kubernetes client using the config at $HOME/.kube/config
func NewForConfig(kubeconfigFilepath string) (*Client, error) {
if kubeconfigFilepath == "" {
home, err := os.UserHomeDir()
if err != nil {
return nil, errors.New("could not find kubernetes config file: " + err.Error())
}
kubeconfigFilepath = filepath.Join(home, ".kube", "config")
}
if err := util.IsReadable(kubeconfigFilepath); err != nil {
return nil, errors.New("could not open " + kubeconfigFilepath + ": " + err.Error())
}
// use the current context in kubeconfigFilepath
config, err := clientcmd.BuildConfigFromFlags("", kubeconfigFilepath)
if err != nil {
return nil, errors.New("could not build kubernetes config: " + err.Error())
}
// create the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return &Client{clientset}, nil
}