Skip to content

Commit c5ed6e0

Browse files
clusterctlv2 add implementation for clusterctl config providers
1 parent 5ea5faa commit c5ed6e0

File tree

7 files changed

+353
-0
lines changed

7 files changed

+353
-0
lines changed

cmd/clusterctl/cmd/config_providers.go

+22
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@ limitations under the License.
1717
package cmd
1818

1919
import (
20+
"fmt"
21+
"os"
22+
"text/tabwriter"
23+
2024
"github.com/pkg/errors"
2125
"github.com/spf13/cobra"
26+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client"
2227
)
2328

2429
type configProvidersOptions struct {
@@ -80,6 +85,23 @@ func init() {
8085
}
8186

8287
func runGetRepositories() error {
88+
c, err := client.New(cfgFile)
89+
if err != nil {
90+
return err
91+
}
92+
93+
repositoryList, err := c.GetProvidersConfig()
94+
if err != nil {
95+
return err
96+
}
97+
98+
w := tabwriter.NewWriter(os.Stdout, 10, 4, 3, ' ', 0)
99+
fmt.Fprintln(w, "NAME\tTYPE\tURL")
100+
for _, r := range repositoryList {
101+
fmt.Fprintf(w, "%s\t%s\t%s\n", r.Name(), r.Type(), r.URL())
102+
}
103+
w.Flush()
104+
83105
return nil
84106
}
85107

cmd/clusterctl/pkg/client/alias.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package client
18+
19+
import (
20+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client/config"
21+
)
22+
23+
// Alias creates local alias for types defined in the low-level library.
24+
// By using local alias, ensures that the users of the API will be forced to import the clusterctl high-level library only.
25+
26+
// Provider defines a provider configuration.
27+
type Provider config.Provider

cmd/clusterctl/pkg/client/client.go

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package client
18+
19+
import (
20+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client/config"
21+
)
22+
23+
// Client is exposes the clusterctl high-level client library
24+
type Client interface {
25+
GetProvidersConfig() ([]Provider, error)
26+
}
27+
28+
// clusterctlClient implements Client.
29+
type clusterctlClient struct {
30+
configClient config.Client
31+
}
32+
33+
// ensure clusterctlClient implements Client.
34+
var _ Client = &clusterctlClient{}
35+
36+
// NewOptions carries the options supported by New
37+
type NewOptions struct {
38+
injectConfig config.Client
39+
}
40+
41+
// Option is a configuration option supplied to New
42+
type Option func(*NewOptions)
43+
44+
// InjectConfig implements a New Option that allows to override the default configuration client used by clusterctl.
45+
func InjectConfig(config config.Client) Option {
46+
return func(c *NewOptions) {
47+
c.injectConfig = config
48+
}
49+
}
50+
51+
// New returns a configClient.
52+
func New(path string, options ...Option) (Client, error) {
53+
return newClusterctlClient(path, options...)
54+
}
55+
56+
func newClusterctlClient(path string, options ...Option) (*clusterctlClient, error) {
57+
cfg := &NewOptions{}
58+
for _, o := range options {
59+
o(cfg)
60+
}
61+
62+
configClient := cfg.injectConfig
63+
if configClient == nil {
64+
c, err := config.New(path)
65+
if err != nil {
66+
return nil, err
67+
}
68+
configClient = c
69+
}
70+
71+
return &clusterctlClient{
72+
configClient: configClient,
73+
}, nil
74+
}
+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package client
18+
19+
import (
20+
"testing"
21+
22+
clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
23+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client/config"
24+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/internal/test"
25+
)
26+
27+
// dummy test to document fakeClient usage
28+
func TestNewFakeClient(t *testing.T) {
29+
// create a fake config with a provider named P1 and a variable named var
30+
repository1Config := config.NewProvider("p1", "url", clusterctlv1.CoreProviderType)
31+
32+
config1 := newFakeConfig().
33+
WithVar("var", "value").
34+
WithProvider(repository1Config)
35+
36+
// create a new fakeClient using the fake config
37+
newFakeClient(config1)
38+
}
39+
40+
type fakeClient struct {
41+
configClient config.Client
42+
internalclient *clusterctlClient
43+
}
44+
45+
var _ Client = &fakeClient{}
46+
47+
func (f fakeClient) GetProvidersConfig() ([]Provider, error) {
48+
return f.internalclient.GetProvidersConfig()
49+
}
50+
51+
// newFakeClient return a fake implementation of the client for high-level clusterctl library, based on th given config.
52+
func newFakeClient(configClient config.Client) *fakeClient {
53+
54+
fake := &fakeClient{}
55+
56+
fake.configClient = configClient
57+
if fake.configClient == nil {
58+
fake.configClient = newFakeConfig()
59+
}
60+
61+
fake.internalclient, _ = newClusterctlClient("fake-config",
62+
InjectConfig(fake.configClient),
63+
)
64+
65+
return fake
66+
}
67+
68+
// newFakeConfig return a fake implementation of the client for low-level config library.
69+
// The implementation uses a FakeReader that stores configuration settings in a config map; you can use
70+
// the WithVar or WithProvider methods to set the config map values.
71+
func newFakeConfig() *fakeConfigClient {
72+
fakeReader := test.NewFakeReader()
73+
74+
client, _ := config.New("fake-config", config.InjectReader(fakeReader))
75+
76+
return &fakeConfigClient{
77+
fakeReader: fakeReader,
78+
internalclient: client,
79+
}
80+
}
81+
82+
type fakeConfigClient struct {
83+
fakeReader *test.FakeReader
84+
internalclient config.Client
85+
}
86+
87+
var _ config.Client = &fakeConfigClient{}
88+
89+
func (f fakeConfigClient) Providers() config.ProvidersClient {
90+
return f.internalclient.Providers()
91+
}
92+
93+
func (f fakeConfigClient) Variables() config.VariablesClient {
94+
return f.internalclient.Variables()
95+
}
96+
97+
func (f *fakeConfigClient) WithVar(key, value string) *fakeConfigClient {
98+
f.fakeReader.WithVar(key, value)
99+
return f
100+
}
101+
102+
func (f *fakeConfigClient) WithProvider(provider config.Provider) *fakeConfigClient {
103+
f.fakeReader.WithProvider(provider.Name(), provider.Type(), provider.URL())
104+
return f
105+
}
106+
107+
var (
108+
bootstrapProviderConfig = config.NewProvider("bootstrap", "url", clusterctlv1.BootstrapProviderType)
109+
)

cmd/clusterctl/pkg/client/config.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package client
18+
19+
import (
20+
"unsafe"
21+
)
22+
23+
func (c *clusterctlClient) GetProvidersConfig() ([]Provider, error) {
24+
r, err := c.configClient.Providers().List()
25+
if err != nil {
26+
return nil, err
27+
}
28+
29+
// Provider is an alias for config.Provider; this makes low level conversion
30+
rr := *(*[]Provider)(unsafe.Pointer(&r))
31+
32+
return rr, nil
33+
}
+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package client
18+
19+
import (
20+
"testing"
21+
22+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client/config"
23+
)
24+
25+
func Test_clusterctlClient_GetProvidersConfig(t *testing.T) {
26+
type field struct {
27+
client Client
28+
}
29+
tests := []struct {
30+
name string
31+
field field
32+
wantProviders []string
33+
wantErr bool
34+
}{
35+
{
36+
name: "Returns default providers",
37+
field: field{
38+
client: newFakeClient(newFakeConfig()),
39+
},
40+
wantProviders: []string{
41+
"aws",
42+
config.ClusterAPIName,
43+
"docker",
44+
"kubeadm",
45+
"vsphere",
46+
},
47+
wantErr: false,
48+
},
49+
{
50+
name: "Returns default providers and custom providers if defined",
51+
field: field{
52+
client: newFakeClient(newFakeConfig().WithProvider(bootstrapProviderConfig)),
53+
},
54+
wantProviders: []string{
55+
"aws",
56+
bootstrapProviderConfig.Name(),
57+
config.ClusterAPIName,
58+
"docker",
59+
"kubeadm",
60+
"vsphere",
61+
},
62+
wantErr: false,
63+
},
64+
}
65+
for _, tt := range tests {
66+
t.Run(tt.name, func(t *testing.T) {
67+
got, err := tt.field.client.GetProvidersConfig()
68+
if (err != nil) != tt.wantErr {
69+
t.Errorf("GetProvidersConfig() error = %v, wantErr %v", err, tt.wantErr)
70+
return
71+
}
72+
73+
if len(got) != len(tt.wantProviders) {
74+
t.Errorf("Init() got = %v items, want %v items", len(got), len(tt.wantProviders))
75+
return
76+
}
77+
78+
for i, g := range got {
79+
w := tt.wantProviders[i]
80+
81+
if g.Name() != w {
82+
t.Errorf("GetProvidersConfig(), Item[%d].Name() got = %v, want = %v ", i, g.Name(), w)
83+
}
84+
}
85+
})
86+
}
87+
}

test/infrastructure/docker/go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
307307
go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
308308
go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
309309
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
310+
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
310311
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
311312
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
312313
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=

0 commit comments

Comments
 (0)