Skip to content

Commit 1b8498d

Browse files
authored
Merge pull request #2027 from fabriziopandini/clusterctl-hack
✨clusterctl: implements hack for generating local overrides
2 parents ef75be8 + 0781bb1 commit 1b8498d

File tree

3 files changed

+189
-6
lines changed

3 files changed

+189
-6
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,6 @@ vendor
5454
tilt.d
5555
tilt-settings.json
5656
.tiltbuild
57+
58+
# User-supplied clusterctl hacks settings
59+
clusterctl-settings.json
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright 2020 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
###################
18+
19+
# local-overrides.py takes in input a list of provider and, for each of them, generates the components YAML from the
20+
# local repositories (the GitHub repositories clone), and finally stores it in the clusterctl local override folder
21+
22+
# prerequisites:
23+
24+
# - the script should be executed from sigs.k8s.io/cluster-api/ by calling cmd/clusterctl/hack/local-overrides.py
25+
# - there should be a sigs.k8s.io/cluster-api/clusterctl-settings.json file with the list of provider for which
26+
# the local overrides should be generated and the list of provider repositories to be included (on top of cluster-api).
27+
# {
28+
# "providers": [ "cluster-api", "kubeadm-bootstrap", "aws"],
29+
# "provider_repos": ["../cluster-api-provider-aws"]
30+
# }
31+
# - for each additional provider repository there should be a sigs.k8s.io/<provider_repo>/clusterctl-settings.json file e.g.
32+
# {
33+
# "name": "aws",
34+
# "config": {
35+
# "componentsFile": "infrastructure-components.yaml",
36+
# "nextVersion": "v0.5.0",
37+
# "type": "InfrastructureProvider"
38+
# }
39+
40+
###################
41+
42+
import json
43+
import subprocess
44+
import os
45+
import errno
46+
47+
settings = {}
48+
49+
providers = {
50+
'cluster-api': {
51+
'componentsFile': 'core-components.yaml',
52+
'nextVersion': 'v0.3.0',
53+
'type': 'CoreProvider',
54+
},
55+
'kubeadm-bootstrap': {
56+
'componentsFile': 'bootstrap-components.yaml',
57+
'nextVersion': 'v0.3.0',
58+
'type': 'BootstrapProvider',
59+
'configFolder': '/bootstrap/kubeadm/config/default',
60+
},
61+
}
62+
63+
validTypes = ['CoreProvider','BootstrapProvider','InfrastructureProvider']
64+
65+
def load_settings():
66+
global settings
67+
try:
68+
settings = json.load(open('clusterctl-settings.json'))
69+
except Exception as e:
70+
raise Exception('failed to load clusterctl-settings.json: {}'.format(e))
71+
72+
def load_providers():
73+
provider_repos = settings.get('provider_repos', [])
74+
for repo in provider_repos:
75+
file = repo + '/clusterctl-settings.json'
76+
try:
77+
provider_details = json.load(open(file))
78+
provider_name = provider_details['name']
79+
provider_config = provider_details['config']
80+
provider_config['repo'] = repo
81+
providers[provider_name] = provider_config
82+
except Exception as e:
83+
raise Exception('failed to load clusterctl-settings.json from repo {}: {}'.format(repo, e))
84+
85+
def execCmd(args):
86+
try:
87+
out = subprocess.Popen(args,
88+
stdout=subprocess.PIPE,
89+
stderr=subprocess.STDOUT)
90+
91+
stdout, stderr = out.communicate()
92+
if stderr is not None:
93+
raise Exception('stderr contains: \n{}'.format(stderr))
94+
95+
return stdout
96+
except Exception as e:
97+
raise Exception('failed to run {}: {}'.format(args, e))
98+
99+
def get_home():
100+
return os.path.expanduser('~')
101+
102+
def write_local_override(provider, version, components_file, components_yaml):
103+
try:
104+
home = get_home()
105+
overrides_folder = os.path.join(home, 'cluster-api', 'overrides')
106+
provider_overrides_folder = os.path.join(overrides_folder, provider, version)
107+
try:
108+
os.makedirs(provider_overrides_folder)
109+
except OSError as e:
110+
if e.errno != errno.EEXIST:
111+
raise
112+
f = open(os.path.join(provider_overrides_folder, components_file), 'w')
113+
f.write(components_yaml)
114+
f.close()
115+
except Exception as e:
116+
raise Exception('failed to write {} to {}: {}'.format(components_file, components_folder, e))
117+
118+
def create_local_overrides():
119+
providerList = settings.get('providers', [])
120+
assert providerList is not None, 'invalid configuration: please define the list of providers to override'
121+
assert len(providerList)>0, 'invalid configuration: please define at least one provider to override'
122+
123+
for provider in providerList:
124+
p = providers.get(provider)
125+
assert p is not None, 'invalid configuration: please specify the configuration for the {} provider'.format(provider)
126+
127+
repo = p.get('repo', '.')
128+
config_folder = p.get('configFolder', '/config/default')
129+
130+
next_version = p.get('nextVersion')
131+
assert next_version is not None, 'invalid configuration for provider {}: please provide nextVersion value'.format(provider)
132+
133+
type = p.get('type')
134+
assert type is not None, 'invalid configuration for provider {}: please provide type value'.format(provider)
135+
assert type in validTypes, 'invalid configuration for provider {}: please use one of {}'.format(provider, ', '.join(validTypes))
136+
137+
components_file = p.get('componentsFile')
138+
assert components_file is not None, 'invalid configuration for provider {}: please provide componentsFile value'.format(provider)
139+
140+
components_yaml = execCmd(['kustomize', 'build', repo + config_folder])
141+
write_local_override(provider, next_version, components_file, components_yaml)
142+
143+
yield provider, type, next_version
144+
145+
146+
def CoreProviderFlag():
147+
return '--core'
148+
149+
def BootstrapProviderFlag():
150+
return '--bootstrap'
151+
152+
def InfrastructureProviderFlag():
153+
return '--infrastructure'
154+
155+
def type_to_flag(type):
156+
switcher = {
157+
'CoreProvider': CoreProviderFlag,
158+
'BootstrapProvider': BootstrapProviderFlag,
159+
'InfrastructureProvider': InfrastructureProviderFlag
160+
}
161+
func = switcher.get(type, lambda: 'Invalid type')
162+
return func()
163+
164+
def print_instructions(overrides):
165+
providerList = settings.get('providers', [])
166+
print ('clusterctl local overrides generated from local repositories for the {} providers.'.format(', '.join(providerList)))
167+
print ('in order to use them, please run:')
168+
print
169+
cmd = 'clusterctl init'
170+
for provider, type, next_version in overrides:
171+
cmd += ' {} {}:{}'.format(type_to_flag(type), provider, next_version)
172+
print (cmd)
173+
print
174+
175+
load_settings()
176+
177+
load_providers()
178+
179+
overrides = create_local_overrides()
180+
181+
print_instructions(overrides)

cmd/clusterctl/pkg/client/config/providers_client.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929

3030
const (
3131
ClusterAPIName = "cluster-api"
32-
KubeadmBootstrapProviderName = "kubeadm"
32+
KubeadmBootstrapProviderName = "kubeadm-bootstrap"
3333
ProvidersConfigKey = "providers"
3434
)
3535

@@ -70,11 +70,11 @@ func (p *providersClient) defaults() []Provider {
7070
// cluster API core provider
7171
&provider{
7272
name: ClusterAPIName,
73-
url: "https://github.com/kubernetes-sigs/cluster-api/releases/latest/cluster-api-components.yaml",
73+
url: "https://github.com/kubernetes-sigs/cluster-api/releases/latest/core-components.yaml",
7474
providerType: clusterctlv1.CoreProviderType,
7575
},
7676

77-
// Infrastructure providersClient
77+
// Infrastructure providers
7878
&provider{
7979
name: "aws",
8080
url: "https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases/latest/infrastructure-components.yaml",
@@ -91,11 +91,10 @@ func (p *providersClient) defaults() []Provider {
9191
providerType: clusterctlv1.InfrastructureProviderType,
9292
},
9393

94-
// Bootstrap providersClient
95-
// TODO: CABPK in v1alpha3 will be included into CAPI, so this entry can be removed as soon as v1alpha3 is ready for test
94+
// Bootstrap providers
9695
&provider{
9796
name: KubeadmBootstrapProviderName,
98-
url: "https://github.com/kubernetes-sigs/cluster-api-bootstrap-provider-kubeadm/releases/latest/bootstrap-components.yaml",
97+
url: "https://github.com/kubernetes-sigs/cluster-api/releases/latest/bootstrap-components.yaml",
9998
providerType: clusterctlv1.BootstrapProviderType,
10099
},
101100
}

0 commit comments

Comments
 (0)