From aa3067cbb766a9c46cca1864ad9ffdcc733f7a4e Mon Sep 17 00:00:00 2001 From: Kostiantyn Kalynovskyi Date: Mon, 27 Apr 2020 11:31:57 -0500 Subject: [PATCH] Add clusterctl resource type. This type would allow us to control behavior of clusterctl modules and choose components we want to install, if we put document of kind Clusterctl into Bundle. In near future we need to generate deepcopy methods for this object, so it can be used with kubernetes schema Relates-To: #170 Change-Id: I2f40a7e9b66e0f7f0bbc8b6874ec45f767416c69 --- .../api/v1alpha1/clusterctl_types.go | 81 +++++++++++++++++++ .../api/v1alpha1/clusterctl_types_test.go | 76 +++++++++++++++++ pkg/document/selectors.go | 11 +++ pkg/document/selectors_test.go | 6 ++ .../testdata/selectors/valid/clusterctl.yaml | 34 ++++++++ .../selectors/valid/kustomization.yaml | 3 +- 6 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 pkg/clusterctl/api/v1alpha1/clusterctl_types.go create mode 100644 pkg/clusterctl/api/v1alpha1/clusterctl_types_test.go create mode 100644 pkg/document/testdata/selectors/valid/clusterctl.yaml diff --git a/pkg/clusterctl/api/v1alpha1/clusterctl_types.go b/pkg/clusterctl/api/v1alpha1/clusterctl_types.go new file mode 100644 index 000000000..081bb60dd --- /dev/null +++ b/pkg/clusterctl/api/v1alpha1/clusterctl_types.go @@ -0,0 +1,81 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package clusterctl + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" +) + +// TODO (kkalynovskyi) add generators for deepcopy methods, so we can use kubernetes schema + +var ( + // GroupVersionKind is group version used to register these objects + GroupVersionKind = schema.GroupVersionKind{Group: "airshipit.org", Version: "v1alpha1", Kind: "Clusterctl"} +) + +// Clusterctl provides information about clusterctl components +type Clusterctl struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Providers []*Provider `json:"providers,omitempty"` + InitOptions *InitOptions `json:"init-options,omitempty"` +} + +// Provider is part of clusterctl config +type Provider struct { + Name string `json:"name,"` + Type string `json:"type,"` + URL string `json:"url,omitempty"` + + // IsClusterctlRepository if set to true, clusterctl provider's repository implementation will be used + // if omitted or set to false, airshipctl repository implementation will be used. + IsClusterctlRepository bool `json:"clusterctl-repository,omitempty"` + + // Map of versions where each key is a version and value is path relative to target path of the manifest + // ignored if IsClusterctlRepository is set to true + Versions map[string]string `json:"versions,omitempty"` +} + +// InitOptions container with exposed clusterctl InitOptions +type InitOptions struct { + // CoreProvider version (e.g. cluster-api:v0.3.0) to add to the management cluster. If unspecified, the + // cluster-api core provider's latest release is used. + CoreProvider string `json:"core-provider,omitempty"` + + // BootstrapProviders and versions (e.g. kubeadm:v0.3.0) to add to the management cluster. + // If unspecified, the kubeadm bootstrap provider's latest release is used. + BootstrapProviders []string `json:"bootstrap-providers,omitempty"` + + // InfrastructureProviders and versions (e.g. aws:v0.5.0) to add to the management cluster. + InfrastructureProviders []string `json:"infrastructure-providers,omitempty"` + + // ControlPlaneProviders and versions (e.g. kubeadm:v0.3.0) to add to the management cluster. + // If unspecified, the kubeadm control plane provider latest release is used. + ControlPlaneProviders []string `json:"control-plane-providers,omitempty"` +} + +// Provider returns provider filtering by name and type +func (c *Clusterctl) Provider(name string, providerType clusterctlv1.ProviderType) *Provider { + t := string(providerType) + for _, prov := range c.Providers { + if prov.Name == name && prov.Type == t { + return prov + } + } + return nil +} diff --git a/pkg/clusterctl/api/v1alpha1/clusterctl_types_test.go b/pkg/clusterctl/api/v1alpha1/clusterctl_types_test.go new file mode 100644 index 000000000..f2f80f91c --- /dev/null +++ b/pkg/clusterctl/api/v1alpha1/clusterctl_types_test.go @@ -0,0 +1,76 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package clusterctl + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" +) + +func TestProvider(t *testing.T) { + cctl := &Clusterctl{ + Providers: []*Provider{ + { + Name: "kubeadm", + URL: "/home/providers/kubeadm/v0.3.5/components.yaml", + Type: "BootstrapProvider", + IsClusterctlRepository: true, + }, + }, + } + tests := []struct { + name string + getName string + getType string + expectedProvider *Provider + }{ + { + name: "repo options exist", + getName: "kubeadm", + getType: "BootstrapProvider", + expectedProvider: &Provider{ + Name: "kubeadm", + URL: "/home/providers/kubeadm/v0.3.5/components.yaml", + Type: "BootstrapProvider", + IsClusterctlRepository: true, + }, + }, + { + name: "repo name does not exist", + getName: "does not exist", + getType: "BootstrapProvider", + expectedProvider: nil, + }, + { + name: "type does not exist", + getName: "kubeadm", + getType: "does not exist", + expectedProvider: nil, + }, + } + + for _, tt := range tests { + getName := tt.getName + getType := tt.getType + expectedProvider := tt.expectedProvider + t.Run(tt.name, func(t *testing.T) { + actualProvider := cctl.Provider(getName, clusterctlv1.ProviderType(getType)) + assert.Equal(t, expectedProvider, actualProvider) + }) + } +} diff --git a/pkg/document/selectors.go b/pkg/document/selectors.go index 4d6090c95..5ac09f70b 100644 --- a/pkg/document/selectors.go +++ b/pkg/document/selectors.go @@ -20,6 +20,8 @@ import ( "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/types" + + airshipv1 "opendev.org/airship/airshipctl/pkg/clusterctl/api/v1alpha1" ) // Selector provides abstraction layer in front of kustomize selector @@ -164,3 +166,12 @@ func NewClusterctlMetadataSelector() Selector { ClusterctlMetadataVersion, ClusterctlMetadataKind) } + +// NewClusterctlSelector returns a selector to get document that controls how clusterctl +// components will be applied +func NewClusterctlSelector() Selector { + return NewSelector().ByGvk( + airshipv1.GroupVersionKind.Group, + airshipv1.GroupVersionKind.Version, + airshipv1.GroupVersionKind.Kind) +} diff --git a/pkg/document/selectors_test.go b/pkg/document/selectors_test.go index 8b4ce1e47..060227773 100644 --- a/pkg/document/selectors_test.go +++ b/pkg/document/selectors_test.go @@ -54,6 +54,12 @@ func TestSelectorsPositive(t *testing.T) { require.NoError(t, err) assert.Len(t, doc, 1) }) + + t.Run("TestNewClusterctlSelector", func(t *testing.T) { + docs, err := bundle.Select(document.NewClusterctlSelector()) + require.NoError(t, err) + assert.Len(t, docs, 1) + }) } func TestSelectorsNegative(t *testing.T) { diff --git a/pkg/document/testdata/selectors/valid/clusterctl.yaml b/pkg/document/testdata/selectors/valid/clusterctl.yaml new file mode 100644 index 000000000..c389f7f19 --- /dev/null +++ b/pkg/document/testdata/selectors/valid/clusterctl.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: airshipit.org/v1alpha1 +kind: Clusterctl +metadata: + labels: + airshipit.org/deploy-k8s: "false" + name: clusterctl-v1 +options: + init-options: + core-provider: "cluster-api:v0.3.3" + bootstrap-providers: + - "kubeadm:v0.3.3" + infrastructure-providers: + - "metal3:v0.3.1" + control-plane-providers: + - "kubeadm:v0.3.3" + config: + providers: + - name: "metal3" + type: "InfrastructureProvider" + versions: + v0.3.1: manifests/function/capm3/v0.3.1 + - name: "kubeadm" + type: "BootstrapProvider" + versions: + v0.3.3: manifests/function/cabpk/v0.3.3 + - name: "cluster-api" + type: "CoreProvider" + versions: + v0.3.3: manifests/function/capi/v0.3.3 + - name: "kubeadm" + type: "ControlPlaneProvider" + versions: + v0.3.3: manifests/function/cacpk/v0.3.3 diff --git a/pkg/document/testdata/selectors/valid/kustomization.yaml b/pkg/document/testdata/selectors/valid/kustomization.yaml index a3c4e8b39..b4474b308 100644 --- a/pkg/document/testdata/selectors/valid/kustomization.yaml +++ b/pkg/document/testdata/selectors/valid/kustomization.yaml @@ -2,4 +2,5 @@ resources: - baremetal.yaml - secret.yaml - argo.yaml - - metadata.yaml \ No newline at end of file + - metadata.yaml + - clusterctl.yaml