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