Skip to content

Commit

Permalink
Implemented adopted cluster using a new template. Renamed the "Manage…
Browse files Browse the repository at this point in the history
…dCluster" to "ClusterDeployment" as well so that it makes sense when using it for adopting existing k8s clusters. Also avoids a conflict with some Azure CRDs.
  • Loading branch information
kylewuolle committed Dec 10, 2024
1 parent a1860eb commit 6193f19
Show file tree
Hide file tree
Showing 77 changed files with 969 additions and 810 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
- name: Run E2E tests
env:
GINKGO_LABEL_FILTER: 'controller'
MANAGED_CLUSTER_NAME: ${{ needs.build.outputs.clustername }}
CLUSTER_DEPLOYMENT_NAME: ${{ needs.build.outputs.clustername }}
IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}'
VERSION: ${{ needs.build.outputs.version }}
run: |
Expand Down Expand Up @@ -162,7 +162,7 @@ jobs:
- name: Run E2E tests
env:
GINKGO_LABEL_FILTER: 'provider:cloud'
MANAGED_CLUSTER_NAME: ${{ needs.build.outputs.clustername }}
CLUSTER_DEPLOYMENT_NAME: ${{ needs.build.outputs.clustername }}
IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}'
VERSION: ${{ needs.build.outputs.version }}
run: |
Expand Down Expand Up @@ -215,7 +215,7 @@ jobs:
- name: Run E2E tests
env:
GINKGO_LABEL_FILTER: 'provider:onprem'
MANAGED_CLUSTER_NAME: ${{ needs.build.outputs.clustername }}
CLUSTER_DEPLOYMENT_NAME: ${{ needs.build.outputs.clustername }}
IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}'
VERSION: ${{ needs.build.outputs.version }}
run: |
Expand Down
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@ dev-templates: templates-generate
dev-release:
@$(YQ) e ".spec.version = \"${VERSION}\"" $(PROVIDER_TEMPLATES_DIR)/hmc-templates/files/release.yaml | $(KUBECTL) -n $(NAMESPACE) apply -f -

.PHONY: dev-adopted-creds
dev-adopted-creds: envsubst
@NAMESPACE=$(NAMESPACE) $(ENVSUBST) -i config/dev/adopted-credentials.yaml | $(KUBECTL) apply -f -

.PHONY: dev-aws-creds
dev-aws-creds: envsubst
@NAMESPACE=$(NAMESPACE) $(ENVSUBST) -i config/dev/aws-credentials.yaml | $(KUBECTL) apply -f -
Expand All @@ -359,11 +363,11 @@ dev-destroy: kind-undeploy registry-undeploy ## Destroy the development environm

.PHONY: dev-mcluster-apply
dev-mcluster-apply: envsubst
@NAMESPACE=$(NAMESPACE) $(ENVSUBST) -no-unset -i config/dev/$(DEV_PROVIDER)-managedcluster.yaml | $(KUBECTL) apply -f -
@NAMESPACE=$(NAMESPACE) $(ENVSUBST) -no-unset -i config/dev/$(DEV_PROVIDER)-clusterdeployment.yaml | $(KUBECTL) apply -f -

.PHONY: dev-mcluster-delete
dev-mcluster-delete: envsubst
@NAMESPACE=$(NAMESPACE) $(ENVSUBST) -no-unset -i config/dev/$(DEV_PROVIDER)-managedcluster.yaml | $(KUBECTL) delete -f -
@NAMESPACE=$(NAMESPACE) $(ENVSUBST) -no-unset -i config/dev/$(DEV_PROVIDER)-clusterdeployment.yaml | $(KUBECTL) delete -f -

.PHONY: dev-creds-apply
dev-creds-apply: dev-$(DEV_PROVIDER)-creds
Expand Down
2 changes: 1 addition & 1 deletion PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ resources:
controller: true
domain: hmc.mirantis.com
group: hmc.mirantis.com
kind: ManagedCluster
kind: ClusterDeployment
path: github.com/Mirantis/hmc/api/v1alpha1
version: v1alpha1
- api:
Expand Down
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ If you want to deploy hosted control plane template, make sure to check
additional notes on Hosted control plane in 2A Docs, see
[Documentation](#documentation).

2. Create the file with the `ManagedCluster` configuration:
2. Create the file with the `ClusterDeployment` configuration:

> [!NOTE]
> Substitute the parameters enclosed in angle brackets with the corresponding
Expand All @@ -140,7 +140,7 @@ additional notes on Hosted control plane in 2A Docs, see

```yaml
apiVersion: hmc.mirantis.com/v1alpha1
kind: ManagedCluster
kind: ClusterDeployment
metadata:
name: <cluster-name>
namespace: <cluster-namespace>
Expand All @@ -152,46 +152,46 @@ spec:
<cluster-configuration>
```

3. Create the `ManagedCluster` object:
3. Create the `ClusterDeployment` object:

`kubectl create -f managedcluster.yaml`
`kubectl create -f ClusterDeployment.yaml`

4. Check the status of the newly created `ManagedCluster` object:
4. Check the status of the newly created `ClusterDeployment` object:

`kubectl -n <managedcluster-namespace> get managedcluster <managedcluster-name> -o=yaml`
`kubectl -n <ClusterDeployment-namespace> get ClusterDeployment <ClusterDeployment-name> -o=yaml`

5. Wait for infrastructure to be provisioned and the cluster to be deployed (the
provisioning starts only when `spec.dryRun` is disabled):

```bash
kubectl -n <managedcluster-namespace> get cluster <managedcluster-name> -o=yaml
kubectl -n <ClusterDeployment-namespace> get cluster <ClusterDeployment-name> -o=yaml
```

> [!NOTE]
> You may also watch the process with the `clusterctl describe` command
> (requires the `clusterctl` CLI to be installed): ``` clusterctl describe
> cluster <managedcluster-name> -n <managedcluster-namespace> --show-conditions
> cluster <ClusterDeployment-name> -n <ClusterDeployment-namespace> --show-conditions
> all ```

6. Retrieve the `kubeconfig` of your managed cluster:

```
kubectl get secret -n hmc-system <managedcluster-name>-kubeconfig -o=jsonpath={.data.value} | base64 -d > kubeconfig
kubectl get secret -n hmc-system <ClusterDeployment-name>-kubeconfig -o=jsonpath={.data.value} | base64 -d > kubeconfig
```

### Dry run

HMC `ManagedCluster` supports two modes: with and without (default) `dryRun`.
HMC `ClusterDeployment` supports two modes: with and without (default) `dryRun`.

If no configuration (`spec.config`) provided, the `ManagedCluster` object will
If no configuration (`spec.config`) provided, the `ClusterDeployment` object will
be populated with defaults (default configuration can be found in the
corresponding `Template` status) and automatically marked as `dryRun`.

Here is an example of the `ManagedCluster` object with default configuration:
Here is an example of the `ClusterDeployment` object with default configuration:

```yaml
apiVersion: hmc.mirantis.com/v1alpha1
kind: ManagedCluster
kind: ClusterDeployment
metadata:
name: <cluster-name>
namespace: <cluster-namespace>
Expand Down Expand Up @@ -226,11 +226,11 @@ After you adjust your configuration and ensure that it passes validation
(`TemplateReady` condition from `status.conditions`), remove the `spec.dryRun`
flag to proceed with the deployment.

Here is an example of a `ManagedCluster` object that passed the validation:
Here is an example of a `ClusterDeployment` object that passed the validation:

```yaml
apiVersion: hmc.mirantis.com/v1alpha1
kind: ManagedCluster
kind: ClusterDeployment
metadata:
name: aws-standalone
namespace: hmc-system
Expand Down Expand Up @@ -259,7 +259,7 @@ spec:
status: "True"
type: HelmChartReady
- lastTransitionTime: "2024-07-22T09:25:49Z"
message: ManagedCluster is ready
message: ClusterDeployment is ready
reason: Succeeded
status: "True"
type: Ready
Expand All @@ -275,7 +275,7 @@ kubectl delete management.hmc hmc
```

> [!NOTE]
> Make sure you have no HMC ManagedCluster objects left in the cluster prior to
> Make sure you have no HMC ClusterDeployment objects left in the cluster prior to
> Management deletion

2. Remove the `hmc` Helm release:
Expand Down
54 changes: 27 additions & 27 deletions api/v1alpha1/indexers.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import (
func SetupIndexers(ctx context.Context, mgr ctrl.Manager) error {
var merr error
for _, f := range []func(context.Context, ctrl.Manager) error{
setupManagedClusterIndexer,
setupManagedClusterServicesIndexer,
setupManagedClusterCredentialIndexer,
setupClusterDeploymentIndexer,
setupClusterDeploymentServicesIndexer,
setupClusterDeploymentCredentialIndexer,
setupReleaseVersionIndexer,
setupReleaseTemplatesIndexer,
setupClusterTemplateChainIndexer,
Expand All @@ -44,35 +44,35 @@ func SetupIndexers(ctx context.Context, mgr ctrl.Manager) error {

// managed cluster

// ManagedClusterTemplateIndexKey indexer field name to extract ClusterTemplate name reference from a ManagedCluster object.
const ManagedClusterTemplateIndexKey = ".spec.template"
// ClusterDeploymentTemplateIndexKey indexer field name to extract ClusterTemplate name reference from a ClusterDeployment object.
const ClusterDeploymentTemplateIndexKey = ".spec.template"

func setupManagedClusterIndexer(ctx context.Context, mgr ctrl.Manager) error {
return mgr.GetFieldIndexer().IndexField(ctx, &ManagedCluster{}, ManagedClusterTemplateIndexKey, ExtractTemplateNameFromManagedCluster)
func setupClusterDeploymentIndexer(ctx context.Context, mgr ctrl.Manager) error {
return mgr.GetFieldIndexer().IndexField(ctx, &ClusterDeployment{}, ClusterDeploymentTemplateIndexKey, ExtractTemplateNameFromClusterDeployment)
}

// ExtractTemplateNameFromManagedCluster returns referenced ClusterTemplate name
// declared in a ManagedCluster object.
func ExtractTemplateNameFromManagedCluster(rawObj client.Object) []string {
cluster, ok := rawObj.(*ManagedCluster)
// ExtractTemplateNameFromClusterDeployment returns referenced ClusterTemplate name
// declared in a ClusterDeployment object.
func ExtractTemplateNameFromClusterDeployment(rawObj client.Object) []string {
cluster, ok := rawObj.(*ClusterDeployment)
if !ok {
return nil
}

return []string{cluster.Spec.Template}
}

// ManagedClusterServiceTemplatesIndexKey indexer field name to extract service templates names from a ManagedCluster object.
const ManagedClusterServiceTemplatesIndexKey = ".spec.services[].Template"
// ClusterDeploymentServiceTemplatesIndexKey indexer field name to extract service templates names from a ClusterDeployment object.
const ClusterDeploymentServiceTemplatesIndexKey = ".spec.services[].Template"

func setupManagedClusterServicesIndexer(ctx context.Context, mgr ctrl.Manager) error {
return mgr.GetFieldIndexer().IndexField(ctx, &ManagedCluster{}, ManagedClusterServiceTemplatesIndexKey, ExtractServiceTemplateNamesFromManagedCluster)
func setupClusterDeploymentServicesIndexer(ctx context.Context, mgr ctrl.Manager) error {
return mgr.GetFieldIndexer().IndexField(ctx, &ClusterDeployment{}, ClusterDeploymentServiceTemplatesIndexKey, ExtractServiceTemplateNamesFromClusterDeployment)
}

// ExtractServiceTemplateNamesFromManagedCluster returns a list of service templates names
// declared in a ManagedCluster object.
func ExtractServiceTemplateNamesFromManagedCluster(rawObj client.Object) []string {
cluster, ok := rawObj.(*ManagedCluster)
// ExtractServiceTemplateNamesFromClusterDeployment returns a list of service templates names
// declared in a ClusterDeployment object.
func ExtractServiceTemplateNamesFromClusterDeployment(rawObj client.Object) []string {
cluster, ok := rawObj.(*ClusterDeployment)
if !ok {
return nil
}
Expand All @@ -85,17 +85,17 @@ func ExtractServiceTemplateNamesFromManagedCluster(rawObj client.Object) []strin
return templates
}

// ManagedClusterCredentialIndexKey indexer field name to extract Credential name reference from a ManagedCluster object.
const ManagedClusterCredentialIndexKey = ".spec.credential"
// ClusterDeploymentCredentialIndexKey indexer field name to extract Credential name reference from a ClusterDeployment object.
const ClusterDeploymentCredentialIndexKey = ".spec.credential"

func setupManagedClusterCredentialIndexer(ctx context.Context, mgr ctrl.Manager) error {
return mgr.GetFieldIndexer().IndexField(ctx, &ManagedCluster{}, ManagedClusterCredentialIndexKey, ExtractCredentialNameFromManagedCluster)
func setupClusterDeploymentCredentialIndexer(ctx context.Context, mgr ctrl.Manager) error {
return mgr.GetFieldIndexer().IndexField(ctx, &ClusterDeployment{}, ClusterDeploymentCredentialIndexKey, ExtractCredentialNameFromClusterDeployment)
}

// ExtractCredentialNameFromManagedCluster returns referenced Credential name
// declared in a ManagedCluster object.
func ExtractCredentialNameFromManagedCluster(rawObj client.Object) []string {
cluster, ok := rawObj.(*ManagedCluster)
// ExtractCredentialNameFromClusterDeployment returns referenced Credential name
// declared in a ClusterDeployment object.
func ExtractCredentialNameFromClusterDeployment(rawObj client.Object) []string {
cluster, ok := rawObj.(*ClusterDeployment)
if !ok {
return nil
}
Expand Down
44 changes: 22 additions & 22 deletions api/v1alpha1/managedcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
)

const (
BlockingFinalizer = "hmc.mirantis.com/cleanup"
ManagedClusterFinalizer = "hmc.mirantis.com/managed-cluster"
BlockingFinalizer = "hmc.mirantis.com/cleanup"
ClusterDeploymentFinalizer = "hmc.mirantis.com/cluster-deployment"

FluxHelmChartNameKey = "helm.toolkit.fluxcd.io/name"
FluxHelmChartNamespaceKey = "helm.toolkit.fluxcd.io/namespace"
Expand All @@ -35,20 +35,20 @@ const (
)

const (
// ManagedClusterKind is the string representation of a ManagedCluster.
ManagedClusterKind = "ManagedCluster"
// ClusterDeploymentKind is the string representation of a ClusterDeployment.
ClusterDeploymentKind = "ClusterDeployment"
// TemplateReadyCondition indicates the referenced Template exists and valid.
TemplateReadyCondition = "TemplateReady"
// HelmChartReadyCondition indicates the corresponding HelmChart is valid and ready.
HelmChartReadyCondition = "HelmChartReady"
// HelmReleaseReadyCondition indicates the corresponding HelmRelease is ready and fully reconciled.
HelmReleaseReadyCondition = "HelmReleaseReady"
// ReadyCondition indicates the ManagedCluster is ready and fully reconciled.
// ReadyCondition indicates the ClusterDeployment is ready and fully reconciled.
ReadyCondition string = "Ready"
)

// ManagedClusterSpec defines the desired state of ManagedCluster
type ManagedClusterSpec struct {
// ClusterDeploymentSpec defines the desired state of ClusterDeployment
type ClusterDeploymentSpec struct {
// Config allows to provide parameters for template customization.
// If no Config provided, the field will be populated with the default values for
// the template and DryRun will be enabled.
Expand Down Expand Up @@ -86,14 +86,14 @@ type ManagedClusterSpec struct {
StopOnConflict bool `json:"stopOnConflict,omitempty"`
}

// ManagedClusterStatus defines the observed state of ManagedCluster
type ManagedClusterStatus struct {
// ClusterDeploymentStatus defines the observed state of ClusterDeployment
type ClusterDeploymentStatus struct {
// Services contains details for the state of services.
Services []ServiceStatus `json:"services,omitempty"`
// Currently compatible exact Kubernetes version of the cluster. Being set only if
// provided by the corresponding ClusterTemplate.
KubernetesVersion string `json:"k8sVersion,omitempty"`
// Conditions contains details for the current state of the ManagedCluster.
// Conditions contains details for the current state of the ClusterDeployment.
Conditions []metav1.Condition `json:"conditions,omitempty"`

// AvailableUpgrades is the list of ClusterTemplate names to which
Expand All @@ -111,27 +111,27 @@ type ManagedClusterStatus struct {
// +kubebuilder:printcolumn:name="status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="Status",priority=0
// +kubebuilder:printcolumn:name="dryRun",type="string",JSONPath=".spec.dryRun",description="Dry Run",priority=1

// ManagedCluster is the Schema for the managedclusters API
type ManagedCluster struct {
// ClusterDeployment is the Schema for the ClusterDeployments API
type ClusterDeployment struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ManagedClusterSpec `json:"spec,omitempty"`
Status ManagedClusterStatus `json:"status,omitempty"`
Spec ClusterDeploymentSpec `json:"spec,omitempty"`
Status ClusterDeploymentStatus `json:"status,omitempty"`
}

func (in *ManagedCluster) HelmValues() (values map[string]any, err error) {
func (in *ClusterDeployment) HelmValues() (values map[string]any, err error) {
if in.Spec.Config != nil {
err = yaml.Unmarshal(in.Spec.Config.Raw, &values)
}
return values, err
}

func (in *ManagedCluster) GetConditions() *[]metav1.Condition {
func (in *ClusterDeployment) GetConditions() *[]metav1.Condition {
return &in.Status.Conditions
}

func (in *ManagedCluster) InitConditions() {
func (in *ClusterDeployment) InitConditions() {
apimeta.SetStatusCondition(in.GetConditions(), metav1.Condition{
Type: TemplateReadyCondition,
Status: metav1.ConditionUnknown,
Expand All @@ -156,19 +156,19 @@ func (in *ManagedCluster) InitConditions() {
Type: ReadyCondition,
Status: metav1.ConditionUnknown,
Reason: ProgressingReason,
Message: "ManagedCluster is not yet ready",
Message: "ClusterDeployment is not yet ready",
})
}

// +kubebuilder:object:root=true

// ManagedClusterList contains a list of ManagedCluster
type ManagedClusterList struct {
// ClusterDeploymentList contains a list of ClusterDeployment
type ClusterDeploymentList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ManagedCluster `json:"items"`
Items []ClusterDeployment `json:"items"`
}

func init() {
SchemeBuilder.Register(&ManagedCluster{}, &ManagedClusterList{})
SchemeBuilder.Register(&ClusterDeployment{}, &ClusterDeploymentList{})
}
2 changes: 1 addition & 1 deletion api/v1alpha1/templates_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (s *HelmSpec) String() string {
// TemplateStatusCommon defines the observed state of Template common for all Template types
type TemplateStatusCommon struct {
// Config demonstrates available parameters for template customization,
// that can be used when creating ManagedCluster objects.
// that can be used when creating ClusterDeployment objects.
Config *apiextensionsv1.JSON `json:"config,omitempty"`
// ChartRef is a reference to a source controller resource containing the
// Helm chart representing the template.
Expand Down
Loading

0 comments on commit 6193f19

Please sign in to comment.