Skip to content

Commit 1882b01

Browse files
clusterctlv2 add Interfaces for Repository low-level factory
1 parent 5ea5faa commit 1882b01

File tree

7 files changed

+486
-0
lines changed

7 files changed

+486
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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 repository
18+
19+
import (
20+
"net/url"
21+
22+
"github.com/pkg/errors"
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+
// Client is used to interact with provider repositories.
28+
// Provider repository are expected to contain two types of YAML files:
29+
// - YAML files defining the provider components (CRD, Controller, RBAC etc.)
30+
// - YAML files defining the cluster templates (Cluster, Machines)
31+
type Client interface {
32+
config.Provider
33+
34+
// Components provide access to YAML file for creating provider components.
35+
Components() ComponentsClient
36+
37+
// Templates provide access to YAML file for generating workload cluster templates.
38+
// Please note that templates are expected to exist for the infrastructure providers only.
39+
Templates(version string) TemplatesClient
40+
}
41+
42+
// repositoryClient implements Client.
43+
type repositoryClient struct {
44+
config.Provider
45+
configVariablesClient config.VariablesClient
46+
repository Repository
47+
}
48+
49+
// ensure repositoryClient implements Client.
50+
var _ Client = &repositoryClient{}
51+
52+
func (c *repositoryClient) Components() ComponentsClient {
53+
return newComponentsClient(c.Provider, c.repository, c.configVariablesClient)
54+
}
55+
56+
func (c *repositoryClient) Templates(version string) TemplatesClient {
57+
return newTemplatesClient(c.Provider, version, c.repository, c.configVariablesClient)
58+
}
59+
60+
// NewOptions carries the options supported by New
61+
type NewOptions struct {
62+
injectRepository Repository
63+
}
64+
65+
// Option is a configuration option supplied to New
66+
type Option func(*NewOptions)
67+
68+
// InjectRepository allows to override the repository implementation to use;
69+
// by default, the repository implementation to use is created according to the
70+
// repository URL.
71+
func InjectRepository(repository Repository) Option {
72+
return func(c *NewOptions) {
73+
c.injectRepository = repository
74+
}
75+
}
76+
77+
// New returns a Client.
78+
func New(provider config.Provider, configVariablesClient config.VariablesClient, options Options) (Client, error) {
79+
return newRepositoryClient(provider, configVariablesClient, options)
80+
}
81+
82+
func newRepositoryClient(provider config.Provider, configVariablesClient config.VariablesClient, options Options) (*repositoryClient, error) {
83+
repository := options.InjectRepository
84+
if repository == nil {
85+
r, err := repositoryFactory(provider, configVariablesClient)
86+
if err != nil {
87+
return nil, errors.Wrapf(err, "failed to get repository client for %q", provider.Name())
88+
}
89+
repository = r
90+
}
91+
92+
return &repositoryClient{
93+
Provider: provider,
94+
repository: repository,
95+
configVariablesClient: configVariablesClient,
96+
}, nil
97+
}
98+
99+
// Options allow to set Client options
100+
type Options struct {
101+
InjectRepository Repository
102+
}
103+
104+
// Repository defines the behavior of a repository implementation.
105+
// clusterctl is designed to support different repository types; each repository implementation should consider
106+
// the following capabilities and provide best support considering the underlying technology.
107+
// 1. Versions awareness: repositories are expected to be aware of the provider version they are hosting, and
108+
// possibly to host more than one version.
109+
// 2. Kustomize awareness: even if it is recommended that provider expose “pre-compiled” YAML files, we want
110+
// to allow usage of clusterctl reading from the “raw” /config directory generated by kubebuilder (developer friendly)
111+
type Repository interface {
112+
// DefaultVersion returns the default provider version returned by a repository.
113+
// In case the repository URL points to latest, this method returns the current latest version; in other cases
114+
// it returns the version of the provider hosted in the repository.
115+
DefaultVersion() string
116+
117+
// RootPath returns the path inside the repository where the YAML file for creating provider components and
118+
// the YAML file for generating workload cluster templates are stored.
119+
// This value is derived from the repository URL; all the paths returned by this interface should be relative to this path.
120+
RootPath() string
121+
122+
// ComponentsPath return the path (a folder name or file name) of the YAML file for creating provider components.
123+
// This value is derived from the repository URL.
124+
ComponentsPath() string
125+
126+
// KustomizeDir returns the path to a folder containing the kustomization.yaml for creating the YAML file provider components.
127+
// This value is derived from the repository URL, and it is used only when the YAML for provider components is spread
128+
// across nested folders inside the repository like e.g. the /config folder generated by kubebuilder.
129+
KustomizeDir() string
130+
131+
// GetFiles returns files for a given provider version.
132+
// If file is a path, the entire content of the path is returned.
133+
GetFiles(version string, path string) (map[string][]byte, error)
134+
}
135+
136+
var _ Repository = &test.FakeRepository{}
137+
138+
//repositoryFactory returns the repository implementation corresponding to the provider URL.
139+
func repositoryFactory(providerConfig config.Provider, configVariablesClient config.VariablesClient) (Repository, error) { //nolint
140+
// parse the repository url
141+
rURL, err := url.Parse(providerConfig.URL())
142+
if err != nil {
143+
return nil, errors.Errorf("failed to parse repository url %q", providerConfig.URL())
144+
}
145+
146+
// if the url is a github repository
147+
//TODO: implement in a follow up PR
148+
149+
// if the url is a local repository
150+
//TODO: implement in a follow up PR
151+
152+
return nil, errors.Errorf("invalid provider url. there are no provider implementation for %q schema", rURL.Scheme)
153+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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 repository
18+
19+
import (
20+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
21+
clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
22+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client/config"
23+
)
24+
25+
// Components wraps a YAML file that defines the provider components
26+
// to be installed in a management cluster (CRD, Controller, RBAC etc.)
27+
// It is important to notice that clusterctl applies a set of processing steps to the “raw” component read
28+
// from the provider repositories:
29+
// 1. In case the provider exposed a component YAML that is not “pre-compiled” (e.g. the /config dir), it uses
30+
// kustomize to create a single component YAML file
31+
// 2. Checks for all the variables in the component YAML file and replace with corresponding config values
32+
// 3. Ensures all the provider components are deployed in the target namespace (apply only to namespaced objects)
33+
// 4. Ensures all the ClusterRoleBinding which are referencing namespaced objects have the name prefixed with the namespace name
34+
// 5. Set the watching namespace for the provider controller
35+
// 6. Adds labels to all the components in order to allow easy identification of the provider objects
36+
type Components interface {
37+
// configuration of the provider the template belongs to.
38+
config.Provider
39+
40+
// Version of the provider.
41+
Version() string
42+
43+
// Variables required by the template.
44+
// This value is derived by the component YAML.
45+
Variables() []string
46+
47+
// TargetNamespace where the provider components will be installed.
48+
// By default this value is derived by the component YAML, but it is possible to override it
49+
// during the creation of the Components object.
50+
TargetNamespace() string
51+
52+
// WatchingNamespace defines the namespace where the provider controller is is watching (empty means all namespaces).
53+
// By default this value is derived by the component YAML, but it is possible to override it
54+
// during the creation of the Components object.
55+
WatchingNamespace() string
56+
57+
// Metadata returns the clusterctl metadata object representing the provider that will be
58+
// generated by this provider components.
59+
Metadata() clusterctlv1.Provider
60+
61+
// Yaml return the provider components in the form of a YAML file.
62+
Yaml() ([]byte, error)
63+
64+
// Objs return the provider components in the form of a list of Unstructured objects.
65+
Objs() []unstructured.Unstructured
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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 repository
18+
19+
import (
20+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client/config"
21+
)
22+
23+
// ComponentsClient has methods to work with yaml file for generating provider components.
24+
// Assets are yaml files to be used for deploying a provider into a management cluster.
25+
type ComponentsClient interface {
26+
Get(version, targetNamespace, watchingNamespace string) (Components, error)
27+
}
28+
29+
// componentsClient implements ComponentsClient.
30+
type componentsClient struct {
31+
provider config.Provider
32+
repository Repository
33+
configVariablesClient config.VariablesClient
34+
}
35+
36+
// ensure componentsClient implements ComponentsClient.
37+
var _ ComponentsClient = &componentsClient{}
38+
39+
// newComponentsClient returns a componentsClient.
40+
func newComponentsClient(provider config.Provider, repository Repository, configVariablesClient config.VariablesClient) *componentsClient {
41+
return &componentsClient{
42+
provider: provider,
43+
repository: repository,
44+
configVariablesClient: configVariablesClient,
45+
}
46+
}
47+
48+
func (f *componentsClient) Get(version, targetNamespace, watchingNamespace string) (Components, error) {
49+
//TODO: implement in a follow up PR
50+
return nil, nil
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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 repository
18+
19+
import (
20+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client/config"
21+
)
22+
23+
// Template wraps a YAML file that defines the cluster objects (Cluster, Machines etc.).
24+
// It is important to notice that clusterctl applies a set of processing steps to the “raw” cluster template YAML read
25+
// from the provider repositories:
26+
// 1. Checks for all the variables in the cluster template YAML file and replace with corresponding config values
27+
// 2. Process go templates contained in the cluster template YAML file
28+
// 3. Ensure all the cluster objects are deployed in the target namespace
29+
type Template interface {
30+
// configuration of the provider the template belongs to.
31+
config.Provider
32+
33+
// Version of the provider the template belongs to.
34+
Version() string
35+
36+
// Flavor implemented by the template (empty means default flavor).
37+
// A flavor is a variant of cluster template supported by the provider, like e.g. Prod, Test.
38+
Flavor() string
39+
40+
// Bootstrap provider used by the cluster template.
41+
Bootstrap() string
42+
43+
// Variables required by the template.
44+
// This value is derived by the template YAML.
45+
Variables() []string
46+
47+
// TargetNamespace where the template objects will be installed.
48+
// This value is inherited by the template options.
49+
TargetNamespace() string
50+
51+
// Yaml file defining all the cluster objects.
52+
Yaml() []byte
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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 repository
18+
19+
import (
20+
"sigs.k8s.io/cluster-api/cmd/clusterctl/pkg/client/config"
21+
)
22+
23+
// TemplateOptions defines a set of well-know variables that all the cluster templates are expected to manage;
24+
// this set of variables defines a simple, day1 experience that will be made accessible via flags in the clusterctl CLI.
25+
// Please note that each provider/each template is allowed to add more variables, but additional variables are exposed
26+
// only via environment variables or the clusterctl configuration file.
27+
type TemplateOptions struct {
28+
ClusterName string
29+
Namespace string
30+
KubernetesVersion string
31+
ControlplaneCount int
32+
WorkerCount int
33+
}
34+
35+
// TemplatesClient has methods to work with templatesClient hosted on a provider repository.
36+
// Templates are yaml files to be used for creating a guest cluster.
37+
type TemplatesClient interface {
38+
Get(flavor, bootstrap string, options TemplateOptions) (Template, error)
39+
}
40+
41+
// templatesClient implements TemplatesClient.
42+
type templatesClient struct {
43+
provider config.Provider
44+
version string
45+
repository Repository
46+
configVariablesClient config.VariablesClient
47+
}
48+
49+
// ensure templatesClient implements TemplatesClient.
50+
var _ TemplatesClient = &templatesClient{}
51+
52+
// newTemplatesClient returns a templatesClient.
53+
func newTemplatesClient(provider config.Provider, version string, repository Repository, configVariablesClient config.VariablesClient) *templatesClient {
54+
return &templatesClient{
55+
provider: provider,
56+
version: version,
57+
repository: repository,
58+
configVariablesClient: configVariablesClient,
59+
}
60+
}
61+
62+
// Get return the template for the flavor/bootstrap provider specified.
63+
// In case the template does not exists, an error is returned.
64+
func (f *templatesClient) Get(flavor, bootstrap string, options TemplateOptions) (Template, error) {
65+
//TODO: implement in a follow up PR
66+
return nil, nil
67+
}

0 commit comments

Comments
 (0)