forked from libopenstorage/stork
/
factory.go
165 lines (143 loc) · 4.8 KB
/
factory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package storkctl
import (
"fmt"
appsops "github.com/portworx/sched-ops/k8s/apps"
"github.com/portworx/sched-ops/k8s/batch"
"github.com/portworx/sched-ops/k8s/core"
dynamicops "github.com/portworx/sched-ops/k8s/dynamic"
externalstorageops "github.com/portworx/sched-ops/k8s/externalstorage"
ocpops "github.com/portworx/sched-ops/k8s/openshift"
storkops "github.com/portworx/sched-ops/k8s/stork"
"github.com/spf13/pflag"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)
const (
outputFormatTable = "table"
outputFormatYaml = "yaml"
outputFormatJSON = "json"
)
type factory struct {
allNamespaces bool
namespace string
kubeconfig string
context string
outputFormat string
watch bool
}
// Factory to be used for command line
type Factory interface {
// BindFlags Binds command flags to the command
BindFlags(flags *pflag.FlagSet)
// BindGetFlags Binds command flags for the get subcommand
BindGetFlags(flags *pflag.FlagSet)
// AllNamespaces Retruns true if the all-namespaces flag was used
AllNamespaces() bool
// GetNamespace Gets the namespace used for the command
GetNamespace() string
// GetAllNamespaces Get all the namespaces that should be used for a command
GetAllNamespaces() ([]string, error)
// GetConfig Get the merged config for the server
GetConfig() (*rest.Config, error)
// RawConfig Gets the raw merged config for the server
RawConfig() (clientcmdapi.Config, error)
// UpdateConfig Updates the config to be used for API calls
UpdateConfig() error
// GetOutputFormat Get the output format
GetOutputFormat() (string, error)
// setOutputFormat Set the output format
setOutputFormat(string)
// setNamespace Set the namespace
setNamespace(string)
// IsWatchSet return true if -w/watch is passed
IsWatchSet() bool
}
// NewFactory Return a new factory interface that can be used by commands
func NewFactory() Factory {
return &factory{}
}
func (f *factory) BindFlags(flags *pflag.FlagSet) {
flags.StringVarP(&f.namespace, "namespace", "n", "default", "If present, the namespace scope for this CLI request")
flags.StringVar(&f.kubeconfig, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests")
flags.StringVar(&f.context, "context", "", "The name of the kubeconfig context to use")
flags.StringVarP(&f.outputFormat, "output", "o", outputFormatTable, "Output format. One of: table|json|yaml")
flags.BoolVarP(&f.watch, "watch", "w", false, "watch stork resourrces")
}
func (f *factory) BindGetFlags(flags *pflag.FlagSet) {
flags.BoolVarP(&f.allNamespaces, "all-namespaces", "", false, "If present, list the requested object(s) across all namespaces.\n"+
"Namespace in current context is ignored even if specified with --namespace.")
}
func (f *factory) AllNamespaces() bool {
return f.allNamespaces
}
func (f *factory) GetNamespace() string {
return f.namespace
}
func (f *factory) GetAllNamespaces() ([]string, error) {
allNamespaces := make([]string, 0)
if f.allNamespaces {
namespaces, err := core.Instance().ListNamespaces(nil)
if err != nil {
return nil, err
}
for _, ns := range namespaces.Items {
allNamespaces = append(allNamespaces, ns.Name)
}
} else {
allNamespaces = append(allNamespaces, f.GetNamespace())
}
return allNamespaces, nil
}
func (f *factory) getKubeconfig() clientcmd.ClientConfig {
configLoadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
configLoadingRules.ExplicitPath = f.kubeconfig
configOverrides := &clientcmd.ConfigOverrides{
CurrentContext: f.context,
}
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(configLoadingRules, configOverrides)
}
func (f *factory) GetConfig() (*rest.Config, error) {
return f.getKubeconfig().ClientConfig()
}
func (f *factory) IsWatchSet() bool {
return f.watch
}
func (f *factory) UpdateConfig() error {
config, err := f.GetConfig()
if err != nil {
return err
}
core.Instance().SetConfig(config)
storkops.Instance().SetConfig(config)
batch.Instance().SetConfig(config)
ocpops.Instance().SetConfig(config)
appsops.Instance().SetConfig(config)
dynamicops.Instance().SetConfig(config)
externalstorageops.Instance().SetConfig(config)
return nil
}
func (f *factory) RawConfig() (clientcmdapi.Config, error) {
config, err := f.getKubeconfig().RawConfig()
if err != nil {
return config, err
}
if f.context != "" {
config.CurrentContext = f.context
}
return config, nil
}
func (f *factory) GetOutputFormat() (string, error) {
switch f.outputFormat {
case outputFormatTable, outputFormatYaml, outputFormatJSON:
return f.outputFormat, nil
default:
return "", fmt.Errorf("unsupported output type %v", f.outputFormat)
}
}
func (f *factory) setOutputFormat(outputFormat string) {
f.outputFormat = outputFormat
}
func (f *factory) setNamespace(namespace string) {
f.namespace = namespace
}