From 0cb69e2baaa8dfeb10cb01e3ffb51116b7f6e35a Mon Sep 17 00:00:00 2001 From: Felix Breuer Date: Wed, 11 Feb 2026 16:23:05 +0100 Subject: [PATCH 1/5] clean repository for open source Signed-off-by: Felix Breuer --- .github/ISSUE_TEMPLATE/enhancement_request.md | 10 - LICENSE | 2 +- OWNERS | 2 + README.md | 128 +++---- docs/machine-class.md | 139 +++++++ docs/release-procedure.md | 55 +++ docs/stackit-iaas-api-analysis.md | 339 ------------------ pkg/provider/apis/provider_spec.go | 2 +- .../validation/validation_secgroup_test.go | 2 +- samples/deployment.yaml | 6 +- samples/machine-class.yaml | 24 +- samples/secret.yaml | 11 +- scripts/Dockerfile_build | 9 - scripts/build-docker.sh | 15 - scripts/build.sh | 27 -- test/e2e/e2e_networking_test.go | 4 +- 16 files changed, 277 insertions(+), 498 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/enhancement_request.md create mode 100644 docs/machine-class.md create mode 100644 docs/release-procedure.md delete mode 100644 docs/stackit-iaas-api-analysis.md delete mode 100644 scripts/Dockerfile_build delete mode 100755 scripts/build-docker.sh delete mode 100755 scripts/build.sh diff --git a/.github/ISSUE_TEMPLATE/enhancement_request.md b/.github/ISSUE_TEMPLATE/enhancement_request.md deleted file mode 100644 index 4179e17e..00000000 --- a/.github/ISSUE_TEMPLATE/enhancement_request.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Enhancement Request -about: Suggest an enhancement -labels: kind/enhancement - ---- - -**What would you like to be added**: - -**Why is this needed**: diff --git a/LICENSE b/LICENSE index 7a4a3ea2..911c1037 100644 --- a/LICENSE +++ b/LICENSE @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2025 Schwarz IT Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/OWNERS b/OWNERS index 7bce7a76..edd44913 100644 --- a/OWNERS +++ b/OWNERS @@ -1,3 +1,5 @@ +# See the OWNERS docs at https://go.k8s.io/owners + reviewers: - machine-controller-manager-provider-stackit-reviewers approvers: diff --git a/README.md b/README.md index 096b2cf4..710f0c1e 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,13 @@ # machine-controller-manager-provider-stackit -[![GitHub License](https://img.shields.io/github/license/stackitcloud/stackit-sdk-go)](https://www.apache.org/licenses/LICENSE-2.0) +[![GitHub License](https://img.shields.io/github/license/stackitcloud/machine-controller-manager-provider-stackit)](https://www.apache.org/licenses/LICENSE-2.0) Out of tree (controller based) implementation for `STACKIT` as a provider for Gardener. -A Machine Controller Manager (MCM) external provider implementation for STACKIT cloud infrastructure. This provider enables Gardener to manage virtual machines on STACKIT using the declarative Kubernetes API. +A Machine Controller Manager (MCM) provider implementation for STACKIT cloud infrastructure. This provider enables Gardener to manage virtual machines on STACKIT using the declarative Kubernetes API. The provider was built following the [MCM provider development guidelines](https://github.com/gardener/machine-controller-manager/blob/master/docs/development/cp_support_new.md) and bootstrapped from the [sample provider template](https://github.com/gardener/machine-controller-manager-provider-sampleprovider). -## Project Structure - -```sh -machine-controller-manager-provider-stackit/ -├── cmd/ -│ └── machine-controller/ -│ └── main.go # Provider entrypoint -├── pkg/ -│ ├── provider/ -│ │ ├── core.go # Core provider implementation -│ │ ├── provider.go # Driver interface implementation -│ │ ├── stackit_client.go # STACKIT client interface -│ │ ├── sdk_client.go # STACKIT SDK wrapper implementation -│ │ ├── helpers.go # SDK type conversion utilities -│ │ ├── apis/ -│ │ │ ├── provider_spec.go # ProviderSpec CRD definitions -│ │ │ └── validation/ # Field validation logic -│ │ └── *_test.go # Unit tests -│ └── spi/ -│ └── spi.go # Service provider interface -├── test/ -│ └── e2e/ # End-to-end integration tests -├── samples/ # Example manifests -├── kubernetes/ # Deployment manifests -└── vendor/ # Go module dependencies -``` - ## Getting Started ### Deployment @@ -45,14 +18,45 @@ See the [samples/](./samples/) directory for example manifests including: - [`machine-class.yaml`](./samples/machine-class.yaml) - MachineClass definition - [`machine.yaml`](./samples/machine.yaml) - Individual Machine example - [`machine-deployment.yaml`](./samples/machine-deployment.yaml) - MachineDeployment for scaled workloads -- [`deployment.yaml`](./kubernetes/deployment.yaml) - Provider controller deployment +- [`deployment.yaml`](./samples/deployment.yaml) - Provider controller deployment + +### Minimal MachineClass Example + +Here's a bare minimum MachineClass configuration: + +```yaml +apiVersion: machine.sapcloud.io/v1alpha1 +kind: MachineClass +metadata: + name: stackit-machine + namespace: default +providerSpec: + region: eu01 + machineType: c2i.2 + imageId: "12345678-1234-1234-1234-123456789012" +secretRef: + name: stackit-credentials + namespace: default +``` -Deploy using standard kubectl commands: +For detailed information on all available configuration fields, see the [MachineClass documentation](./docs/machine-class.md). + +## Local Testing & Development + +Use the Makefile targets for development and testing: ```sh -kubectl apply -f samples/secret.yaml -kubectl apply -f samples/machine-class.yaml -kubectl apply -f samples/machine.yaml +# Run tests +make test + +# Verify code formatting and run all checks +make verify + +# Format code +make fmt + +# Build container image +make image ``` ## STACKIT SDK Integration @@ -65,13 +69,11 @@ Each provider instance is bound to a single STACKIT project via the service acco The provider requires STACKIT credentials to be provided via a Kubernetes Secret. The Secret must contain the following fields: -| Field | Required | Description | -| ------------------- | -------- | ---------------------------------------------------------------- | -| `projectId` | Yes | STACKIT project UUID | -| `serviceAccountKey` | Yes | STACKIT service account credentials (JSON format) | -| `region` | Yes | STACKIT region (e.g., `eu01-1`, `eu01-2`) | -| `userData` | No | Default cloud-init user data (can be overridden in ProviderSpec) | -| `networkId` | No | Default network UUID (can be overridden in ProviderSpec) | +| Field | Required | Description | +| --------------------- | -------- | ---------------------------------------------------------------- | +| `project-id` | Yes | STACKIT project UUID | +| `serviceaccount.json` | Yes | STACKIT service account credentials (JSON format) | +| `userData` | No | Default cloud-init user data (can be overridden in ProviderSpec) | The service account key should be obtained from the STACKIT Portal (Project Settings → Service Accounts → Create Key) and contains JWT credentials and a private key for secure authentication. @@ -81,46 +83,14 @@ The service account key should be obtained from the STACKIT Portal (Project Sett The provider supports the following environment variables for configuration: -| Variable | Default | Description | -| ---------------------- | ------------- | ------------------------------------------------------------------ | -| `STACKIT_API_ENDPOINT` | (SDK default) | Override STACKIT API endpoint URL (useful for testing) | -| `STACKIT_NO_AUTH` | `false` | Skip authentication (for testing with mock servers, set to `true`) | +| Variable | Default | Description | +| ----------------------- | ------------- | ------------------------------------------------------------------ | +| `STACKIT_IAAS_ENDPOINT` | (SDK default) | Override STACKIT API endpoint URL (useful for testing) | +| `STACKIT_TOKEN_BASEURL` | (SDK default) | Override STACKIT Token endpoint URL (useful for testing) | +| `STACKIT_NO_AUTH` | `false` | Skip authentication (for testing with mock servers, set to `true`) | **Note:** `STACKIT_NO_AUTH=true` is only intended for testing environments with mock servers. It skips the authenticaiton step and communicates with the STACKIT API without authenticating itself. Do not use in production. -## Configuration Reference - -### ProviderSpec Fields - -| Field | Type | Required | Description | -| --------------------- | ---------------------- | -------- | ------------------------------------------------ | -| `machineType` | string | Yes | STACKIT server type (e.g., "c2i.2", "m2i.8") | -| `imageId` | string | Yes | UUID of the OS image | -| `labels` | map[string]string | No | Labels for server identification | -| `networking` | NetworkingSpec | No | Network configuration (NetworkID or NICIDs) | -| `securityGroups` | []string | No | Security group names | -| `userData` | string | No | Cloud-init user data (overrides Secret.userData) | -| `bootVolume` | BootVolumeSpec | No | Boot disk configuration | -| `volumes` | []string | No | UUIDs of additional volumes to attach | -| `keypairName` | string | No | SSH keypair name | -| `availabilityZone` | string | No | Availability zone (e.g., "eu01-1") | -| `affinityGroup` | string | No | UUID of affinity group | -| `serviceAccountMails` | []string | No | Service account email addresses (max 1) | -| `agent` | AgentSpec | No | STACKIT agent configuration | -| `metadata` | map[string]interface{} | No | Custom metadata key-value pairs | - -### Local Testing - -Use the local development environment for rapid iteration: - -```sh -# Set up dev environment -just dev - -# Or run provider locally for debugging -just start -``` - ## References ### Machine Controller Manager @@ -144,4 +114,4 @@ just start - [STACKIT Portal](https://portal.stackit.cloud/) - STACKIT management console - [Service Accounts](https://docs.stackit.cloud/stackit/en/service-accounts-134415819.html) - Creating and managing service accounts - [Service Account Keys](https://docs.stackit.cloud/stackit/en/usage-of-the-service-account-keys-in-stackit-175112464.html) - API authentication setup -- [IaaS API Documentation](https://docs.stackit.cloud/) - STACKIT IaaS REST API reference +- [IaaS API v2 Documentation](https://docs.api.stackit.cloud/documentation/iaas/version/v2) - STACKIT IaaS REST API reference diff --git a/docs/machine-class.md b/docs/machine-class.md new file mode 100644 index 00000000..d6af3971 --- /dev/null +++ b/docs/machine-class.md @@ -0,0 +1,139 @@ +# MachineClass ProviderSpec + +This document describes the STACKIT MachineClass ProviderSpec schema and validation rules used by the machine-controller-manager-provider-stackit. + +## Overview + +A MachineClass defines how STACKIT servers should be created. The ProviderSpec is the STACKIT-specific section of the MachineClass and contains all server configuration fields. + +## Required Fields + +- `region` (string): STACKIT region such as "eu01" or "eu02". +- `machineType` (string): STACKIT server type such as "c2i.2" or "m2i.8". +- `imageId` (string): UUID of the image to boot from, unless `bootVolume.source` is set. +- `networking` (object): Must be set and must specify either `networkId` or `nicIds`. + +## ProviderSpec Fields + +| Field | Type | Required | Description | +| --------------------- | ---------------------- | -------- | ------------------------------------------------------------- | +| `region` | string | Yes | STACKIT region (e.g., "eu01", "eu02"). | +| `machineType` | string | Yes | STACKIT server type (e.g., "c2i.2", "m2i.8"). | +| `imageId` | string | Yes\* | Image UUID. Required unless `bootVolume.source` is specified. | +| `labels` | map[string]string | No | Labels for server identification. | +| `networking` | NetworkingSpec | Yes | Network configuration (either `networkId` or `nicIds`). | +| `allowedAddresses` | []string | No | CIDR ranges allowed for anti-spoofing bypass. | +| `securityGroups` | []string | No | Security group UUIDs. | +| `userData` | string | No | Cloud-init user data (overrides Secret.userData). | +| `bootVolume` | BootVolumeSpec | No | Boot disk configuration. | +| `volumes` | []string | No | UUIDs of existing volumes to attach. | +| `keypairName` | string | No | SSH keypair name. | +| `availabilityZone` | string | No | Availability zone (e.g., "eu01-1"). | +| `affinityGroup` | string | No | UUID of affinity group. | +| `serviceAccountMails` | []string | No | Service account emails (max 1). | +| `agent` | AgentSpec | No | STACKIT agent configuration. | +| `metadata` | map[string]interface{} | No | Freeform metadata. | + +## NetworkingSpec + +Exactly one of the following must be set: + +- `networkId` (string): UUID of the network to attach. +- `nicIds` ([]string): UUIDs of pre-created NICs. + +## BootVolumeSpec + +- `deleteOnTermination` (bool, optional): Delete boot volume with server. Default is true. +- `performanceClass` (string, optional): Storage performance tier (for example, "standard", "premium"). +- `size` (int, optional): Size in GB. Must be at least the image size. +- `source` (BootVolumeSourceSpec, optional): Use this instead of `imageId`. + +### BootVolumeSourceSpec + +- `type` (string): One of "image", "snapshot", or "volume". +- `id` (string): UUID of the source object. + +## AgentSpec + +- `provisioned` (bool, optional): Whether the STACKIT agent is installed. + +## Validation Rules + +- `region` must match `^[a-z0-9]+$` (example: "eu01"). +- `machineType` must match `^[a-z]+\d+[a-z]*\.\d+[a-z]*(\.[a-z]+\d+)*$` (examples: "c2i.2", "m2i.8"). +- `imageId`, `volumes[]`, and `affinityGroup` must be valid UUIDs. +- `availabilityZone` must match `^[a-z0-9]+-\d+$` (example: "eu01-1"). +- `keypairName` maximum length is 127 and may contain only `A-Z`, `a-z`, `0-9`, `@`, `.`, `_`, `-`. +- `labels` keys and values follow Kubernetes label rules and are limited to 63 characters. +- `allowedAddresses` entries must be valid CIDR blocks. +- `serviceAccountMails` allows a maximum of 1 entry, and each must be a valid email address. +- `networking` is required and must set exactly one of `networkId` or `nicIds`. + +## Secret Requirements + +MachineClass references a Secret via `secretRef`. The Secret must include: + +- `project-id`: STACKIT project UUID. +- `serviceaccount.json`: Service account key JSON. +- `userData` (optional): Default cloud-init user data. Can be overridden by ProviderSpec `userData`. + +## Examples + +Minimal example: + +```yaml +apiVersion: machine.sapcloud.io/v1alpha1 +kind: MachineClass +metadata: + name: minimal-mc + namespace: default +providerSpec: + region: "eu01" + machineType: "c2i.2" + imageId: "550e8400-e29b-41d4-a716-446655440000" + networking: + networkId: "770e8400-e29b-41d4-a716-446655440000" +secretRef: + name: test-secret + namespace: default +``` + +Extended example: + +```yaml +apiVersion: machine.sapcloud.io/v1alpha1 +kind: MachineClass +metadata: + name: full-example-mc + namespace: default +providerSpec: + region: "eu01" + machineType: "c2i.2" + imageId: "550e8400-e29b-41d4-a716-446655440000" + networking: + networkId: "770e8400-e29b-41d4-a716-446655440000" + securityGroups: + - "660e8400-e29b-41d4-a716-446655440000" + userData: | + #cloud-config + runcmd: + - echo "Bootstrapped" + bootVolume: + size: 50 + performanceClass: "standard" + volumes: + - "880e8400-e29b-41d4-a716-446655440000" + keypairName: "my-ssh-key" + availabilityZone: "eu01-1" + affinityGroup: "880e8400-e29b-41d4-a716-446655440000" + serviceAccountMails: + - "my-service@sa.stackit.cloud" + agent: + provisioned: true + metadata: + environment: "production" + cost-center: "12345" +secretRef: + name: test-secret + namespace: default +``` diff --git a/docs/release-procedure.md b/docs/release-procedure.md new file mode 100644 index 00000000..ca33a471 --- /dev/null +++ b/docs/release-procedure.md @@ -0,0 +1,55 @@ +# Release Procedure + +## Table of Contents + +- [Overview](#overview) +- [General Information](#general-information) +- [Automated Release Process (Primary Method)](#automated-release-process-primary-method) +- [Manual Release Process (Fallback Method)](#manual-release-process-fallback-method) + +## Overview + +This document outlines the standard procedure for creating new releases of the STACKIT machine-controller-manager. + +## General Information + +- **Versioning:** Versioning follows official [SemVer 2.0](https://semver.org/) +- **CI/CD System:** All release and image builds are managed by our **Prow CI** infrastructure. + +--- + +## Automated Release Process (Primary Method) + +The primary release method is automated using a tool called `release-tool`. This process is designed to be straightforward and require minimal manual intervention. + +1. **Draft Creation:** On every successful merge (post-submit) to the `main` branch, a Prow job automatically runs the `release-tool`. This tool creates a new draft release on GitHub or updates the existing one with a changelog generated from recent commits. +2. **Publishing the Release:** When the draft is ready, navigate to the repository's "Releases" page on GitHub. Locate the draft, review the changelog, replace the placeholder with your GitHub handle and publish it by clicking the "Publish release" button. + +Publishing the release automatically creates the corresponding Git tag (e.g., `v1.3.1`), which triggers a separate Prow job to build the final container images and attach them to the GitHub release. + +--- + +## Manual Release Process (Fallback Method) + +If the `release-tool` or its associated Prow job fails, you can manually trigger a release by creating and pushing a Git tag from the appropriate release branch. + +1. **Check out the release branch:** Ensure you have the latest changes from the correct release branch. + + ```bash + git checkout main + git pull origin main + ``` + +2. **Create the Git tag:** Create a new, annotated tag for the release, following semantic versioning. + + ```bash + git tag v2.1.0 + ``` + +3. **Push the tag to the remote repository:** + + ```bash + git push origin v2.1.0 + ``` + +Pushing a tag that starts with `v` (e.g., `v2.1.0`) automatically triggers the same Prow release job that builds and publishes the final container images. You may need to manually update the release notes on GitHub afterward. diff --git a/docs/stackit-iaas-api-analysis.md b/docs/stackit-iaas-api-analysis.md deleted file mode 100644 index f21be440..00000000 --- a/docs/stackit-iaas-api-analysis.md +++ /dev/null @@ -1,339 +0,0 @@ -# STACKIT IAAS API Analysis for MCM Provider - -> **Generated:** 2025-10-28 -> **Source:** STACKIT API mock server OpenAPI spec - -## Overview - -This document analyzes the STACKIT IAAS API to inform the design of our Machine Controller Manager provider implementation. - -## API Endpoints for Server (VM) Management - -### Core CRUD Operations - -| Operation | HTTP Method | Endpoint | MCM Method | -| ------------- | ----------- | --------------------------------------------- | ------------------ | -| List servers | GET | `/v1/projects/{projectId}/servers` | ListMachines() | -| Create server | POST | `/v1/projects/{projectId}/servers` | CreateMachine() | -| Get server | GET | `/v1/projects/{projectId}/servers/{serverId}` | GetMachineStatus() | -| Update server | PATCH | `/v1/projects/{projectId}/servers/{serverId}` | (optional) | -| Delete server | DELETE | `/v1/projects/{projectId}/servers/{serverId}` | DeleteMachine() | - -### Lifecycle Operations - -Additional endpoints available (may be useful for future enhancements): - -- `/v1/projects/{projectId}/servers/{serverId}/start` - Start stopped server -- `/v1/projects/{projectId}/servers/{serverId}/stop` - Stop running server -- `/v1/projects/{projectId}/servers/{serverId}/reboot` - Reboot server -- `/v1/projects/{projectId}/servers/{serverId}/resize` - Change machine type -- `/v1/projects/{projectId}/servers/{serverId}/deallocate` - Deallocate resources -- `/v1/projects/{projectId}/servers/{serverId}/rescue` - Enter rescue mode -- `/v1/projects/{projectId}/servers/{serverId}/console` - Access console -- `/v1/projects/{projectId}/servers/{serverId}/log` - Get server logs - -### Networking Operations - -- `/v1/projects/{projectId}/servers/{serverId}/nics` - Manage NICs -- `/v1/projects/{projectId}/servers/{serverId}/networks/{networkId}` - Attach/detach networks -- `/v1/projects/{projectId}/servers/{serverId}/public-ips/{publicIpId}` - Manage public IPs -- `/v1/projects/{projectId}/servers/{serverId}/security-groups/{securityGroupId}` - Manage security groups - -### Storage Operations - -- `/v1/projects/{projectId}/servers/{serverId}/volume-attachments` - Manage volume attachments - -### Service Account Operations - -- `/v1/projects/{projectId}/servers/{serverId}/service-accounts` - Manage service account access - -## CreateServerPayload Schema - -### Required Fields - -- **`name`** (string) - Server name (MCM will use Machine CR name) -- **`machineType`** (string) - Machine/instance type (e.g., "c2i.2", "m2i.8") - -### Optional Fields - -**Compute Configuration:** - -- `imageId` (UUID) - OS image to use for boot disk -- `availabilityZone` (string) - Availability zone for server placement -- `affinityGroup` (UUID) - Affinity/anti-affinity group for server placement - -**Storage Configuration:** - -- `bootVolume` (object) - Boot disk configuration - - Likely includes size, type, etc. (TBD: check nested schema) -- `volumes` (UUID[]) - Additional volume IDs to attach at creation - -**Networking Configuration:** - -- `networking` (object) - Network configuration - - Two variants: `CreateServerNetworking` or `CreateServerNetworkingWithNics` - - TBD: Investigate exact structure -- `securityGroups` (string[]) - Security group names (writeOnly) - -**Access Configuration:** - -- `keypairName` (string) - SSH keypair name for access -- `serviceAccountMails` (string[]) - Service account emails for server identity - -**Metadata & Customization:** - -- `labels` (object/map) - Key-value labels for tagging and identification -- `metadata` (object/map) - Additional metadata -- `userData` (string) - Cloud-init/user data script (base64 encoded?) - -**Agent Configuration:** - -- `agent` (object) - STACKIT agent configuration - - TBD: Investigate purpose and structure - -### Read-Only Response Fields - -These fields are returned when getting/listing servers but cannot be set on creation: - -**Identifiers & Status:** - -- `id` (UUID) - Server unique identifier -- `status` (string) - Server lifecycle status -- `powerStatus` (string) - Power state of the server - -**Network Information:** - -- `nics` (array) - Network interface card details - -**Timestamps:** - -- `createdAt` (ISO 8601) - Server creation timestamp -- `launchedAt` (ISO 8601) - Server launch timestamp -- `updatedAt` (ISO 8601) - Last update timestamp - -**Maintenance & Errors:** - -- `maintenanceWindow` (object) - Maintenance schedule -- `errorMessage` (string) - Error details if server is in error state - -## Supporting Resources - -### Machine Types - -- Endpoint: `/v1/projects/{projectId}/machine-types` -- Get specific type: `/v1/projects/{projectId}/machine-types/{machineType}` -- Used to validate `machineType` field - -### Images - -- Endpoint: `/v1/projects/{projectId}/images` -- Get specific image: `/v1/projects/{projectId}/images/{imageId}` -- Used to validate `imageId` field - -### Keypairs - -- Endpoint: `/v1/keypairs` -- Get specific keypair: `/v1/keypairs/{keypairName}` -- Used to validate `keypairName` field - -### Networks - -- Endpoint: `/v1/projects/{projectId}/networks` -- Required for networking configuration - -### Availability Zones - -- Endpoint: `/v1/availability-zones` -- Used to validate `availabilityZone` field - -## ProviderSpec Design Recommendations - -Based on the API analysis, our ProviderSpec should include: - -```go -type ProviderSpec struct { - // Required fields - MachineType string `json:"machineType"` // e.g., "c2i.2", "m2i.8" - - // Compute configuration - ImageID string `json:"imageId"` // OS image UUID - AvailabilityZone string `json:"availabilityZone,omitempty"` // AZ name - AffinityGroup string `json:"affinityGroup,omitempty"` // Affinity group UUID - - // Storage configuration - BootVolume *BootVolumeSpec `json:"bootVolume,omitempty"` // Boot disk config - Volumes []string `json:"volumes,omitempty"` // Additional volume UUIDs - - // Networking configuration - Networking *NetworkingSpec `json:"networking"` // Network config - SecurityGroups []string `json:"securityGroups,omitempty"` // Security group names - - // Access configuration - KeypairName string `json:"keypairName,omitempty"` // SSH key - ServiceAccountMails []string `json:"serviceAccountMails,omitempty"` // Service accounts - - // Metadata & customization - Labels map[string]string `json:"labels,omitempty"` // For tagging/identification - Metadata map[string]string `json:"metadata,omitempty"` // Additional metadata - UserData string `json:"userData,omitempty"` // Cloud-init script - - // Agent configuration - Agent *AgentSpec `json:"agent,omitempty"` // STACKIT agent config -} - -// Nested types (TBD: Define based on API spec) -type BootVolumeSpec struct { - // TODO: Define fields from API schema -} - -type NetworkingSpec struct { - // TODO: Define fields from CreateServerNetworking schema -} - -type AgentSpec struct { - // TODO: Define fields from ServerAgent schema -} -``` - -## Server Identification Strategy - -### ProviderID Format - -Format: `stackit:///` - -Example: `stackit://my-project-123/550e8400-e29b-41d4-a716-446655440000` - -**Rationale:** - -- Unique across STACKIT projects -- Contains both project and server ID for easy API calls -- Follows pattern used by other cloud providers (aws://, azure://) - -### Server Tagging via Labels - -Use the `labels` field for MCM identification and mapping: - -| Label Key | Value | Purpose | -| ---------------------------- | ----------------- | ----------------------------------------------- | -| `kubernetes.io/machine` | Machine CR name | Map server to Kubernetes Machine | -| `kubernetes.io/machineclass` | MachineClass name | Map server to MachineClass for orphan detection | - -Example labels: - -```json -{ - "kubernetes.io/machine": "worker-pool-a-12345", - "kubernetes.io/machineclass": "worker-pool-a" -} -``` - -**Critical for:** - -- ListMachines() - Filter servers by MachineClass -- Orphan VM detection - Identify servers without corresponding Machine CRs -- Debugging - Trace servers back to Kubernetes objects - -## Server Status Mapping - -Need to map STACKIT server status values to MCM/Kubernetes states. - -**TODO:** Document exact status values from: - -1. Real STACKIT API documentation -2. Testing with mock server -3. Observing real server lifecycle - -Expected status values (to be confirmed): - -- `CREATING` / `BUILDING` - Server is being created -- `ACTIVE` / `RUNNING` - Server is running -- `STOPPED` / `SHUTOFF` - Server is stopped -- `DELETING` - Server is being deleted -- `ERROR` - Server encountered an error -- `UNKNOWN` - Status cannot be determined - -**MCM Status Codes:** - -- Use `codes.OK` for running servers -- Use `codes.NotFound` for deleted/not-found servers -- Use `codes.Unknown` for error states -- Use `codes.Unavailable` for servers that are starting/stopping - -## Authentication & Authorization - -**Project ID:** Required in all API paths (`/v1/projects/{projectId}/...`) - -**Authentication Methods (TBD):** - -- API tokens -- Service account credentials -- OAuth 2.0 - -**Secret Structure (proposed):** - -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: stackit-credentials -type: Opaque -stringData: - projectId: "my-project-123" - # One of: - apiToken: "..." - # OR - serviceAccountEmail: "..." - serviceAccountKey: "..." # JSON key -``` - -**Environment Variables (for e2e tests):** - -- `STACKIT_API_ENDPOINT` - API base URL -- `STACKIT_PROJECT_ID` - Project ID -- `STACKIT_NO_AUTH=true` - Bypass auth for mock server - -## Next Steps - -### Immediate (Phase 1.2 - API Research) - -- [ ] Investigate nested schemas: - - [ ] `BootVolume` structure - - [ ] `CreateServerNetworking` vs `CreateServerNetworkingWithNics` - - [ ] `ServerAgent` structure -- [ ] Document server status enum values -- [ ] Check real STACKIT API documentation for: - - [ ] Authentication methods - - [ ] Rate limiting - - [ ] Error response formats - - [ ] Pagination for list operations -- [ ] Test mock server endpoints: - - [ ] Create server request/response - - [ ] List servers with filtering - - [ ] Get server by ID - - [ ] Delete server - -### Phase 1.3 - ProviderSpec Design - -- [ ] Define complete ProviderSpec with all nested types -- [ ] Create example `samples/machine-class.yaml` -- [ ] Create example `samples/secret.yaml` -- [ ] Define validation rules for each field -- [ ] Write validation unit tests (TDD) - -### Phase 1.4 - Technical Design - -- [ ] Document error handling strategy -- [ ] Define retry/backoff policies -- [ ] Create sequence diagrams for: - - [ ] CreateMachine flow - - [ ] DeleteMachine flow - - [ ] GetMachineStatus flow - - [ ] ListMachines flow - -## References - -- **Mock Server Repository:** `github.com/stackit-controllers-k8s/stackit-api-mockservers` -- **OpenAPI Spec Location:** `config/apis/iaas/specs/openapi/iaas.json` -- **Real API Specs:** `github.com/stackitcloud/stackit-api-specifications/tree/main/services/iaas` -- **MCM Documentation:** https://gardener.cloud/docs/other-components/machine-controller-manager/ -- **Provider Implementation Guide:** https://gardener.cloud/docs/other-components/machine-controller-manager/cp_support_new/ diff --git a/pkg/provider/apis/provider_spec.go b/pkg/provider/apis/provider_spec.go index e05d82b4..88afffd3 100644 --- a/pkg/provider/apis/provider_spec.go +++ b/pkg/provider/apis/provider_spec.go @@ -28,7 +28,7 @@ type ProviderSpec struct { // Optional field. If specified, these ranges are configured as AllowedAddresses on the network interface of the server to bypass anti-spoofing rules. AllowedAddresses []string `json:"allowedAddresses,omitempty"` - // SecurityGroups are the names of security groups to attach to the server + // SecurityGroups are the UUIDs of security groups to attach to the server // Optional field. If not specified, the project's default security group will be used. SecurityGroups []string `json:"securityGroups,omitempty"` diff --git a/pkg/provider/apis/validation/validation_secgroup_test.go b/pkg/provider/apis/validation/validation_secgroup_test.go index eecbcd7c..5bc3da07 100644 --- a/pkg/provider/apis/validation/validation_secgroup_test.go +++ b/pkg/provider/apis/validation/validation_secgroup_test.go @@ -34,7 +34,7 @@ var _ = Describe("ValidateProviderSpecNSecret", func() { Context("SecurityGroups validation", func() { It("should succeed with valid SecurityGroups", func() { - providerSpec.SecurityGroups = []string{"default", "web-servers"} + providerSpec.SecurityGroups = []string{"550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002"} errors := ValidateProviderSpecNSecret(providerSpec, secret) Expect(errors).To(BeEmpty()) }) diff --git a/samples/deployment.yaml b/samples/deployment.yaml index 46fd30b6..b9f9cf0c 100644 --- a/samples/deployment.yaml +++ b/samples/deployment.yaml @@ -1,6 +1,6 @@ # Sample deployment file, used to run Machine Controller Manager on your cluster -apiVersion: apps/v1 # Version may change based on kubernetes version +apiVersion: apps/v1 kind: Deployment metadata: name: machine-controller-manager @@ -13,7 +13,8 @@ spec: spec: containers: - name: machine-controller-manager - image:eu.gcr.io/gardener-project/gardener/machine-controller-manager:v0.28.0-dev-793b105c41adfc434e07107decaf1ac67fc1fd3f + # NOTE: adjust version + image: europe-docker.pkg.dev/gardener-project/releases/gardener/machine-controller-manager:v0.61.1 imagePullPolicy: Always command: - ./machine-controller-manager @@ -48,6 +49,7 @@ spec: - --machine-safety-orphan-vms-period=30m # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. - --v=3 + # NOTE: adjust version image: ghcr.io/stackitcloud/machine-controller-manager-provider-stackit:latest imagePullPolicy: IfNotPresent livenessProbe: diff --git a/samples/machine-class.yaml b/samples/machine-class.yaml index 43b66049..67aca93e 100644 --- a/samples/machine-class.yaml +++ b/samples/machine-class.yaml @@ -4,6 +4,9 @@ metadata: name: test-mc namespace: default providerSpec: + # Required: STACKIT region (e.g., "eu01", "eu02") + region: "eu01" + # Required: STACKIT machine type (e.g., "c2i.2", "m2i.8") machineType: "c2i.2" @@ -26,11 +29,11 @@ providerSpec: # - "880e8400-e29b-41d4-a716-446655440000" # - "990e8400-e29b-41d4-a716-446655440000" - # Optional: Security groups to apply to the server + # Optional: Security group UUIDs to apply to the server # If not specified, the project's default security group will be used securityGroups: - - "default" - - "web-servers" + - "550e8400-e29b-41d4-a716-446655440001" + - "550e8400-e29b-41d4-a716-446655440002" # Optional: Cloud-init user data for VM bootstrapping # Can be used to override/customize Secret.userData for this specific MachineClass @@ -38,7 +41,7 @@ providerSpec: # Note: Secret.userData is typically required by MCM for node bootstrapping # Use this to add MachineClass-specific customizations userData: | - #cloud-config + # cloud-config runcmd: - echo "Machine bootstrapped via ProviderSpec" - apt-get update @@ -55,6 +58,7 @@ metadata: name: minimal-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" secretRef: @@ -69,13 +73,14 @@ metadata: name: custom-userdata-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # UserData in ProviderSpec overrides Secret.userData # Useful for MachineClass-specific bootstrapping (e.g., different software per class) # Make sure this still includes necessary bootstrap commands for node registration! userData: | - #cloud-config + # cloud-config package_update: true package_upgrade: true packages: @@ -98,6 +103,7 @@ metadata: name: custom-bootvolume-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # BootVolume allows fine-grained control over boot disk @@ -125,6 +131,7 @@ metadata: name: with-volumes-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # Volumes: attach existing volumes by UUID @@ -144,6 +151,7 @@ metadata: name: full-storage-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # Custom boot volume configuration @@ -165,6 +173,7 @@ metadata: name: with-keypair-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # KeypairName: SSH keypair for server access @@ -185,6 +194,7 @@ metadata: name: with-az-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # AvailabilityZone: Specify the AZ where the server will be created @@ -204,6 +214,7 @@ metadata: name: with-affinity-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # AffinityGroup: UUID of affinity group to control server placement @@ -224,6 +235,7 @@ metadata: name: with-service-accounts-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # ServiceAccountMails: Email addresses of service accounts to associate with the server @@ -245,6 +257,7 @@ metadata: name: with-agent-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # Agent: Configure the STACKIT agent on the server @@ -265,6 +278,7 @@ metadata: name: with-metadata-mc namespace: default providerSpec: + region: "eu01" machineType: "c2i.2" imageId: "550e8400-e29b-41d4-a716-446655440000" # Metadata: Generic JSON object for storing arbitrary key-value pairs diff --git a/samples/secret.yaml b/samples/secret.yaml index f3df77de..958bc823 100644 --- a/samples/secret.yaml +++ b/samples/secret.yaml @@ -6,7 +6,7 @@ metadata: type: Opaque stringData: # STACKIT project ID (UUID format) - projectId: "12345678-1234-1234-1234-123456789012" + project-id: "12345678-1234-1234-1234-123456789012" # STACKIT Service Account Key (JSON format) # @@ -25,7 +25,7 @@ stringData: # # Security: Never commit this secret to source control! # Use Kubernetes secrets management or external secret stores. - serviceAccountKey: | + serviceaccount.json: | { "credentials": { "iss": "service-account-email@sa.stackit.cloud", @@ -35,12 +35,9 @@ stringData: "privateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----" } - # STACKIT region (required by SDK v1.0.0+) - # Valid regions: eu01-1, eu01-2, etc. - region: "eu01-1" - # Cloud-init user data for VM bootstrapping + # optional userData: | - #cloud-config + # cloud-config runcmd: - echo "Machine bootstrapped" diff --git a/scripts/Dockerfile_build b/scripts/Dockerfile_build deleted file mode 100644 index e9dbd040..00000000 --- a/scripts/Dockerfile_build +++ /dev/null @@ -1,9 +0,0 @@ -# Dockerfile for building binary inside Docker (exports to host) - -FROM golang:1.25.5 AS builder -WORKDIR /workspace -COPY . . -RUN ./scripts/build.sh - -FROM scratch AS export -COPY --from=builder /workspace/build/machine-controller /machine-controller diff --git a/scripts/build-docker.sh b/scripts/build-docker.sh deleted file mode 100755 index c4f66982..00000000 --- a/scripts/build-docker.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -# Build binary inside Docker container (no local Go required) - -set -euo pipefail - -OUTPUT_DIR="${OUTPUT_DIR:-build}" - -echo "Building binary in Docker container..." - -docker build \ - --file scripts/Dockerfile_build \ - --output "${OUTPUT_DIR}" \ - . - -echo "✓ Binary built via Docker: ${OUTPUT_DIR}/machine-controller" diff --git a/scripts/build.sh b/scripts/build.sh deleted file mode 100755 index e33f33c8..00000000 --- a/scripts/build.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Build configuration -BINARY_NAME="${BINARY_NAME:-machine-controller}" -OUTPUT_DIR="${OUTPUT_DIR:-build}" -OUTPUT_PATH="${OUTPUT_DIR}/${BINARY_NAME}" - -# Colors for output -GREEN='\033[0;32m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -echo -e "${BLUE}Building ${BINARY_NAME}...${NC}" -echo " Output: ${OUTPUT_PATH}" - -# Create output directory -mkdir -p "${OUTPUT_DIR}" - -# Build with CGO disabled for static binary (required for Alpine) -CGO_ENABLED=0 GO111MODULE=on go build \ - -mod=vendor \ - -o "${OUTPUT_PATH}" \ - cmd/machine-controller/main.go - -echo -e "${GREEN}✓ Build complete: ${OUTPUT_PATH}${NC}" diff --git a/test/e2e/e2e_networking_test.go b/test/e2e/e2e_networking_test.go index b2c6d782..f14a90b4 100644 --- a/test/e2e/e2e_networking_test.go +++ b/test/e2e/e2e_networking_test.go @@ -186,8 +186,8 @@ providerSpec: networking: networkId: "770e8400-e29b-41d4-a716-446655440000" securityGroups: - - "default" - - "web-servers" + - "550e8400-e29b-41d4-a716-446655440001" + - "550e8400-e29b-41d4-a716-446655440002" labels: test: "networking-securitygroups" secretRef: From e9c3200cedb2c4079ea2bea8415afc58eb88e1ac Mon Sep 17 00:00:00 2001 From: Felix Breuer Date: Thu, 12 Feb 2026 11:55:22 +0100 Subject: [PATCH 2/5] write local development guide Signed-off-by: Felix Breuer --- Makefile | 18 +- README.md | 6 +- config/crd/kustomization.yaml | 7 - .../machine.sapcloud.io_machineclasses.yaml | 127 ---- ...achine.sapcloud.io_machinedeployments.yaml | 552 ------------------ config/crd/machine.sapcloud.io_machines.yaml | 324 ---------- .../crd/machine.sapcloud.io_machinesets.yaml | 435 -------------- config/default/deployment.yaml | 71 --- config/default/kustomization.yaml | 9 - config/default/rbac.yaml | 134 ----- .../development/deployment-patches.yaml | 16 - .../overlays/development/kustomization.yaml | 11 - config/overlays/e2e/deployment-patches.yaml | 38 -- config/overlays/e2e/kustomization.yaml | 53 -- config/overlays/e2e/namespace.yaml | 4 - docs/development.md | 104 ++++ docs/machine-class.md | 2 +- pkg/client/sdk.go | 2 +- pkg/provider/apis/validation/validation.go | 2 +- samples/deployment.yaml | 132 +++-- 20 files changed, 193 insertions(+), 1854 deletions(-) delete mode 100644 config/crd/kustomization.yaml delete mode 100644 config/crd/machine.sapcloud.io_machineclasses.yaml delete mode 100644 config/crd/machine.sapcloud.io_machinedeployments.yaml delete mode 100644 config/crd/machine.sapcloud.io_machines.yaml delete mode 100644 config/crd/machine.sapcloud.io_machinesets.yaml delete mode 100644 config/default/deployment.yaml delete mode 100644 config/default/kustomization.yaml delete mode 100644 config/default/rbac.yaml delete mode 100644 config/overlays/development/deployment-patches.yaml delete mode 100644 config/overlays/development/kustomization.yaml delete mode 100644 config/overlays/e2e/deployment-patches.yaml delete mode 100644 config/overlays/e2e/kustomization.yaml delete mode 100644 config/overlays/e2e/namespace.yaml create mode 100644 docs/development.md diff --git a/Makefile b/Makefile index 16560220..5422a8bf 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SHELL = /usr/bin/env bash -o pipefail .SHELLFLAGS = -ec SOURCES := Makefile go.mod go.sum $(shell find $(DEST) -name '*.go' 2>/dev/null) VERSION ?= $(shell git describe --dirty --tags --match='v*' 2>/dev/null || git rev-parse --short HEAD) -REGISTRY ?= reg3.infra.ske.eu01.stackit.cloud +REGISTRY ?= ghcr.io REPO ?= stackitcloud/machine-controller-manager-provider-stackit PUSH ?= true PLATFORMS ?= amd64 arm64 @@ -78,3 +78,19 @@ mocks: $(MOCKGEN) .PHONY: generate generate: mocks go generate ./... + +.PHONY: start +start: + go run \ + cmd/machine-controller/main.go \ + --control-kubeconfig=$(CONTROL_KUBECONFIG) \ + --target-kubeconfig=$(TARGET_KUBECONFIG) \ + --namespace=$(CONTROL_NAMESPACE) \ + --machine-creation-timeout=20m \ + --machine-drain-timeout=5m \ + --machine-health-timeout=10m \ + --machine-pv-detach-timeout=2m \ + --machine-safety-apiserver-statuscheck-timeout=30s \ + --machine-safety-apiserver-statuscheck-period=1m \ + --machine-safety-orphan-vms-period=30m \ + --v=3 \ No newline at end of file diff --git a/README.md b/README.md index 710f0c1e..a4235683 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The provider was built following the [MCM provider development guidelines](https ## Getting Started -### Deployment +### Examples See the [samples/](./samples/) directory for example manifests including: @@ -43,7 +43,9 @@ For detailed information on all available configuration fields, see the [Machine ## Local Testing & Development -Use the Makefile targets for development and testing: +Local development runs the provider and MCM against a real Gardener shoot on STACKIT (kind is not suitable for this provider). Follow the steps in the [local development guide](./docs/development.md). + +Use the Makefile targets for testing: ```sh # Run tests diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml deleted file mode 100644 index 0d5da00a..00000000 --- a/config/crd/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - machine.sapcloud.io_machineclasses.yaml - - machine.sapcloud.io_machinedeployments.yaml - - machine.sapcloud.io_machines.yaml - - machine.sapcloud.io_machinesets.yaml diff --git a/config/crd/machine.sapcloud.io_machineclasses.yaml b/config/crd/machine.sapcloud.io_machineclasses.yaml deleted file mode 100644 index f0cd9d51..00000000 --- a/config/crd/machine.sapcloud.io_machineclasses.yaml +++ /dev/null @@ -1,127 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - name: machineclasses.machine.sapcloud.io -spec: - group: machine.sapcloud.io - names: - kind: MachineClass - listKind: MachineClassList - plural: machineclasses - shortNames: - - mcc - singular: machineclass - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: |- - MachineClass can be used to templatize and re-use provider configuration - across multiple Machines / MachineSets / MachineDeployments. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - credentialsSecretRef: - description: |- - CredentialsSecretRef can optionally store the credentials (in this case the SecretRef does not need to store them). - This might be useful if multiple machine classes with the same credentials but different user-datas are used. - properties: - name: - description: name is unique within a namespace to reference a secret - resource. - type: string - namespace: - description: namespace defines the space within which the secret name - must be unique. - type: string - type: object - x-kubernetes-map-type: atomic - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - nodeTemplate: - description: NodeTemplate contains subfields to track all node resources - and other node info required to scale nodegroup from zero - properties: - architecture: - description: CPU Architecture of the node belonging to nodeGroup - type: string - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Capacity contains subfields to track all node resources - required to scale nodegroup from zero - type: object - instanceType: - description: Instance type of the node belonging to nodeGroup - type: string - region: - description: Region of the expected node belonging to nodeGroup - type: string - virtualCapacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: VirtualCapacity represents the expected Node 'virtual' - capacity ie comprising virtual extended resources. - type: object - zone: - description: Zone of the expected node belonging to nodeGroup - type: string - required: - - capacity - - instanceType - - region - - zone - type: object - x-kubernetes-preserve-unknown-fields: true - provider: - description: Provider is the combination of name and location of cloud-specific - drivers. - type: string - providerSpec: - description: Provider-specific configuration to use during node creation. - type: object - x-kubernetes-preserve-unknown-fields: true - secretRef: - description: SecretRef stores the necessary secrets such as credentials - or userdata. - properties: - name: - description: name is unique within a namespace to reference a secret - resource. - type: string - namespace: - description: namespace defines the space within which the secret name - must be unique. - type: string - type: object - x-kubernetes-map-type: atomic - required: - - providerSpec - type: object - served: true - storage: true diff --git a/config/crd/machine.sapcloud.io_machinedeployments.yaml b/config/crd/machine.sapcloud.io_machinedeployments.yaml deleted file mode 100644 index d836282a..00000000 --- a/config/crd/machine.sapcloud.io_machinedeployments.yaml +++ /dev/null @@ -1,552 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - name: machinedeployments.machine.sapcloud.io -spec: - group: machine.sapcloud.io - names: - kind: MachineDeployment - listKind: MachineDeploymentList - plural: machinedeployments - shortNames: - - mcd - singular: machinedeployment - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Total number of ready machines targeted by this machine deployment. - jsonPath: .status.readyReplicas - name: Ready - type: integer - - description: Number of desired machines. - jsonPath: .spec.replicas - name: Desired - type: integer - - description: Total number of non-terminated machines targeted by this machine - deployment that have the desired template spec. - jsonPath: .status.updatedReplicas - name: Up-to-date - type: integer - - description: Total number of available machines (ready for at least minReadySeconds) - targeted by this machine deployment. - jsonPath: .status.availableReplicas - name: Available - type: integer - - description: |- - CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: MachineDeployment enables declarative updates for machines and - MachineSets. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Specification of the desired behavior of the MachineDeployment. - properties: - minReadySeconds: - description: |- - Minimum number of seconds for which a newly created machine should be ready - without any of its container crashing, for it to be considered available. - Defaults to 0 (machine will be considered available as soon as it is ready) - format: int32 - type: integer - paused: - description: |- - Indicates that the MachineDeployment is paused and will not be processed by the - MachineDeployment controller. - type: boolean - progressDeadlineSeconds: - description: |- - The maximum time in seconds for a MachineDeployment to make progress before it - is considered to be failed. The MachineDeployment controller will continue to - process failed MachineDeployments and a condition with a ProgressDeadlineExceeded - reason will be surfaced in the MachineDeployment status. Note that progress will - not be estimated during the time a MachineDeployment is paused. This is not set - by default, which is treated as infinite deadline. - format: int32 - type: integer - replicas: - description: |- - Number of desired machines. This is a pointer to distinguish between explicit - zero and not specified. Defaults to 0. - format: int32 - type: integer - revisionHistoryLimit: - description: |- - The number of old MachineSets to retain to allow rollback. - This is a pointer to distinguish between explicit zero and not specified. - format: int32 - type: integer - rollbackTo: - description: |- - DEPRECATED. - The config this MachineDeployment is rolling back to. Will be cleared after rollback is done. - properties: - revision: - description: The revision to rollback to. If set to 0, rollback - to the last revision. - format: int64 - type: integer - type: object - selector: - description: |- - Label selector for machines. Existing MachineSets whose machines are - selected by this will be the ones affected by this MachineDeployment. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - strategy: - description: The MachineDeployment strategy to use to replace existing - machines with new ones. - properties: - inPlaceUpdate: - description: |- - InPlaceUpdate update config params. Present only if MachineDeploymentStrategyType = - InPlaceUpdate. - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be scheduled above the desired number of - machines. - Value can be an absolute number (ex: 5) or a percentage of desired machines (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Example: when this is set to 30%, the new machine set can be scaled up immediately when - the update starts, such that the total number of old and new machines does not exceed - 130% of desired machines. Once old machines have been killed, - new machine set can be scaled up further, ensuring that total number of machines running - at any time during the update is utmost 130% of desired machines. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired machines (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Example: when this is set to 30%, the old machine set can be scaled down to 70% of desired machines - immediately when the update starts. Once new machines are ready, old machine set - can be scaled down further, followed by scaling up the new machine set, ensuring - that the total number of machines available at all times during the update is at - least 70% of desired machines. - x-kubernetes-int-or-string: true - orchestrationType: - description: OrchestrationType specifies the orchestration - type for the inplace update. - type: string - type: object - rollingUpdate: - description: |- - Rolling update config params. Present only if MachineDeploymentStrategyType = - RollingUpdate. - properties: - maxSurge: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be scheduled above the desired number of - machines. - Value can be an absolute number (ex: 5) or a percentage of desired machines (ex: 10%). - This can not be 0 if MaxUnavailable is 0. - Absolute number is calculated from percentage by rounding up. - Example: when this is set to 30%, the new machine set can be scaled up immediately when - the update starts, such that the total number of old and new machines does not exceed - 130% of desired machines. Once old machines have been killed, - new machine set can be scaled up further, ensuring that total number of machines running - at any time during the update is utmost 130% of desired machines. - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: |- - The maximum number of machines that can be unavailable during the update. - Value can be an absolute number (ex: 5) or a percentage of desired machines (ex: 10%). - Absolute number is calculated from percentage by rounding down. - This can not be 0 if MaxSurge is 0. - Example: when this is set to 30%, the old machine set can be scaled down to 70% of desired machines - immediately when the update starts. Once new machines are ready, old machine set - can be scaled down further, followed by scaling up the new machine set, ensuring - that the total number of machines available at all times during the update is at - least 70% of desired machines. - x-kubernetes-int-or-string: true - type: object - type: - description: Type of MachineDeployment. Can be "Recreate" or "RollingUpdate". - Default is RollingUpdate. - type: string - type: object - template: - description: Template describes the machines that will be created. - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: |- - Specification of the desired behavior of the machine. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - class: - description: Class contains the machineclass attributes of - a machine - properties: - apiGroup: - description: API group to which it belongs - type: string - kind: - description: Kind for machine class - type: string - name: - description: Name of machine class - type: string - type: object - creationTimeout: - description: MachineCreationTimeout is the timeout after which - machinie creation is declared failed. - type: string - disableHealthTimeout: - description: |- - DisableHealthTimeout if set to true, health timeout will be ignored. Leading to machine never being declared failed. - This is intended to be used only for in-place updates. - type: boolean - drainTimeout: - description: MachineDraintimeout is the timeout after which - machine is forcefully deleted. - type: string - healthTimeout: - description: MachineHealthTimeout is the timeout after which - machine is declared unhealhty/failed. - type: string - inPlaceUpdateTimeout: - description: MachineInPlaceUpdateTimeout is the timeout after - which in-place update is declared failed. - type: string - maxEvictRetries: - description: MaxEvictRetries is the number of retries that - will be attempted while draining the node. - format: int32 - type: integer - nodeConditions: - description: NodeConditions are the set of conditions if set - to true for MachineHealthTimeOut, machine will be declared - failed. - type: string - nodeTemplate: - description: NodeTemplateSpec describes the data a node should - have when created from a template - properties: - metadata: - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: NodeSpec describes the attributes that a - node is created with. - properties: - configSource: - description: 'Deprecated: Previously used to specify - the source of the node''s configuration for the - DynamicKubeletConfig feature. This feature is removed.' - properties: - configMap: - description: ConfigMap is a reference to a Node's - ConfigMap - properties: - kubeletConfigKey: - description: |- - KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure - This field is required in all cases. - type: string - name: - description: |- - Name is the metadata.name of the referenced ConfigMap. - This field is required in all cases. - type: string - namespace: - description: |- - Namespace is the metadata.namespace of the referenced ConfigMap. - This field is required in all cases. - type: string - resourceVersion: - description: |- - ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. - This field is forbidden in Node.Spec, and required in Node.Status. - type: string - uid: - description: |- - UID is the metadata.UID of the referenced ConfigMap. - This field is forbidden in Node.Spec, and required in Node.Status. - type: string - required: - - kubeletConfigKey - - name - - namespace - type: object - type: object - externalID: - description: |- - Deprecated. Not all kubelets will set this field. Remove field after 1.13. - see: https://issues.k8s.io/61966 - type: string - podCIDR: - description: PodCIDR represents the pod IP range assigned - to the node. - type: string - podCIDRs: - description: |- - podCIDRs represents the IP ranges assigned to the node for usage by Pods on that node. If this - field is specified, the 0th entry must match the podCIDR field. It may contain at most 1 value for - each of IPv4 and IPv6. - items: - type: string - type: array - x-kubernetes-list-type: set - providerID: - description: 'ID of the node assigned by the cloud - provider in the format: ://' - type: string - taints: - description: If specified, the node's taints. - items: - description: |- - The node this Taint is attached to has the "effect" on - any pod that does not tolerate the Taint. - properties: - effect: - description: |- - Required. The effect of the taint on pods - that do not tolerate the taint. - Valid effects are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Required. The taint key to be applied - to a node. - type: string - timeAdded: - description: |- - TimeAdded represents the time at which the taint was added. - It is only written for NoExecute taints. - format: date-time - type: string - value: - description: The taint value corresponding to - the taint key. - type: string - required: - - effect - - key - type: object - type: array - x-kubernetes-list-type: atomic - unschedulable: - description: |- - Unschedulable controls node schedulability of new pods. By default, node is schedulable. - More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration - type: boolean - type: object - type: object - providerID: - description: ProviderID represents the provider's unique ID - given to a machine - type: string - type: object - type: object - required: - - template - type: object - status: - description: Most recently observed status of the MachineDeployment. - properties: - availableReplicas: - description: Total number of available machines (ready for at least - minReadySeconds) targeted by this MachineDeployment. - format: int32 - type: integer - collisionCount: - description: |- - Count of hash collisions for the MachineDeployment. The MachineDeployment controller uses this - field as a collision avoidance mechanism when it needs to create the name for the - newest MachineSet. - format: int32 - type: integer - conditions: - description: Represents the latest available observations of a MachineDeployment's - current state. - items: - description: MachineDeploymentCondition describes the state of a - MachineDeployment at a certain point. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - lastUpdateTime: - description: The last time this condition was updated. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of MachineDeployment condition. - type: string - required: - - status - - type - type: object - type: array - failedMachines: - description: FailedMachines has summary of machines on which lastOperation - Failed - items: - description: MachineSummary store the summary of machine. - properties: - lastOperation: - description: Last operation refers to the status of the last - operation performed - properties: - description: - description: Description of the current operation - type: string - errorCode: - description: ErrorCode of the current operation if any - type: string - lastUpdateTime: - description: Last update time of current operation - format: date-time - type: string - state: - description: State of operation - type: string - type: - description: Type of operation - type: string - type: object - name: - description: Name of the machine object - type: string - ownerRef: - description: OwnerRef - type: string - providerID: - description: ProviderID represents the provider's unique ID - given to a machine - type: string - type: object - type: array - observedGeneration: - description: The generation observed by the MachineDeployment controller. - format: int64 - type: integer - readyReplicas: - description: Total number of ready machines targeted by this MachineDeployment. - format: int32 - type: integer - replicas: - description: Total number of non-terminated machines targeted by this - MachineDeployment (their labels match the selector). - format: int32 - type: integer - unavailableReplicas: - description: |- - Total number of unavailable machines targeted by this MachineDeployment. This is the total number of - machines that are still required for the MachineDeployment to have 100% available capacity. They may - either be machines that are running but not yet available or machines that still have not been created. - format: int32 - type: integer - updatedReplicas: - description: Total number of non-terminated machines targeted by this - MachineDeployment that have the desired template spec. - format: int32 - type: integer - type: object - type: object - served: true - storage: true - subresources: - scale: - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} diff --git a/config/crd/machine.sapcloud.io_machines.yaml b/config/crd/machine.sapcloud.io_machines.yaml deleted file mode 100644 index 9378f027..00000000 --- a/config/crd/machine.sapcloud.io_machines.yaml +++ /dev/null @@ -1,324 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - name: machines.machine.sapcloud.io -spec: - group: machine.sapcloud.io - names: - kind: Machine - listKind: MachineList - plural: machines - shortNames: - - mc - singular: machine - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Current status of the machine. - jsonPath: .status.currentStatus.phase - name: Status - type: string - - description: |- - CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - description: Node backing the machine object - jsonPath: .metadata.labels.node - name: Node - type: string - - description: ProviderID of the infra instance backing the machine object - jsonPath: .spec.providerID - name: ProviderID - priority: 1 - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: Machine is the representation of a physical or virtual machine. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec contains the specification of the machine - properties: - class: - description: Class contains the machineclass attributes of a machine - properties: - apiGroup: - description: API group to which it belongs - type: string - kind: - description: Kind for machine class - type: string - name: - description: Name of machine class - type: string - type: object - creationTimeout: - description: MachineCreationTimeout is the timeout after which machinie - creation is declared failed. - type: string - disableHealthTimeout: - description: |- - DisableHealthTimeout if set to true, health timeout will be ignored. Leading to machine never being declared failed. - This is intended to be used only for in-place updates. - type: boolean - drainTimeout: - description: MachineDraintimeout is the timeout after which machine - is forcefully deleted. - type: string - healthTimeout: - description: MachineHealthTimeout is the timeout after which machine - is declared unhealhty/failed. - type: string - inPlaceUpdateTimeout: - description: MachineInPlaceUpdateTimeout is the timeout after which - in-place update is declared failed. - type: string - maxEvictRetries: - description: MaxEvictRetries is the number of retries that will be - attempted while draining the node. - format: int32 - type: integer - nodeConditions: - description: NodeConditions are the set of conditions if set to true - for MachineHealthTimeOut, machine will be declared failed. - type: string - nodeTemplate: - description: NodeTemplateSpec describes the data a node should have - when created from a template - properties: - metadata: - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: NodeSpec describes the attributes that a node is - created with. - properties: - configSource: - description: 'Deprecated: Previously used to specify the source - of the node''s configuration for the DynamicKubeletConfig - feature. This feature is removed.' - properties: - configMap: - description: ConfigMap is a reference to a Node's ConfigMap - properties: - kubeletConfigKey: - description: |- - KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure - This field is required in all cases. - type: string - name: - description: |- - Name is the metadata.name of the referenced ConfigMap. - This field is required in all cases. - type: string - namespace: - description: |- - Namespace is the metadata.namespace of the referenced ConfigMap. - This field is required in all cases. - type: string - resourceVersion: - description: |- - ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. - This field is forbidden in Node.Spec, and required in Node.Status. - type: string - uid: - description: |- - UID is the metadata.UID of the referenced ConfigMap. - This field is forbidden in Node.Spec, and required in Node.Status. - type: string - required: - - kubeletConfigKey - - name - - namespace - type: object - type: object - externalID: - description: |- - Deprecated. Not all kubelets will set this field. Remove field after 1.13. - see: https://issues.k8s.io/61966 - type: string - podCIDR: - description: PodCIDR represents the pod IP range assigned - to the node. - type: string - podCIDRs: - description: |- - podCIDRs represents the IP ranges assigned to the node for usage by Pods on that node. If this - field is specified, the 0th entry must match the podCIDR field. It may contain at most 1 value for - each of IPv4 and IPv6. - items: - type: string - type: array - x-kubernetes-list-type: set - providerID: - description: 'ID of the node assigned by the cloud provider - in the format: ://' - type: string - taints: - description: If specified, the node's taints. - items: - description: |- - The node this Taint is attached to has the "effect" on - any pod that does not tolerate the Taint. - properties: - effect: - description: |- - Required. The effect of the taint on pods - that do not tolerate the taint. - Valid effects are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Required. The taint key to be applied to - a node. - type: string - timeAdded: - description: |- - TimeAdded represents the time at which the taint was added. - It is only written for NoExecute taints. - format: date-time - type: string - value: - description: The taint value corresponding to the taint - key. - type: string - required: - - effect - - key - type: object - type: array - x-kubernetes-list-type: atomic - unschedulable: - description: |- - Unschedulable controls node schedulability of new pods. By default, node is schedulable. - More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration - type: boolean - type: object - type: object - providerID: - description: ProviderID represents the provider's unique ID given - to a machine - type: string - type: object - status: - description: Status contains fields depicting the status - properties: - addresses: - description: |- - Addresses of this machines. This field is only present if the MCM provider runs without a target cluster and may - be used by clients to determine how to connect to the machine, instead of the `Node.status.addresses` field. - items: - description: NodeAddress contains information for the node's address. - properties: - address: - description: The node address. - type: string - type: - description: Node address type, one of Hostname, ExternalIP - or InternalIP. - type: string - required: - - address - - type - type: object - type: array - conditions: - description: Conditions of this machine, same as node - items: - description: NodeCondition contains condition information for a - node. - properties: - lastHeartbeatTime: - description: Last time we got an update on a given condition. - format: date-time - type: string - lastTransitionTime: - description: Last time the condition transit from one status - to another. - format: date-time - type: string - message: - description: Human readable message indicating details about - last transition. - type: string - reason: - description: (brief) reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of node condition. - type: string - required: - - status - - type - type: object - type: array - currentStatus: - description: Current status of the machine object - properties: - lastUpdateTime: - description: Last update time of current status - format: date-time - type: string - phase: - description: MachinePhase is a label for the condition of a machine - at the current time. - type: string - timeoutActive: - type: boolean - type: object - lastKnownState: - description: |- - LastKnownState can store details of the last known state of the VM by the plugins. - It can be used by future operation calls to determine current infrastucture state - type: string - lastOperation: - description: Last operation refers to the status of the last operation - performed - properties: - description: - description: Description of the current operation - type: string - errorCode: - description: ErrorCode of the current operation if any - type: string - lastUpdateTime: - description: Last update time of current operation - format: date-time - type: string - state: - description: State of operation - type: string - type: - description: Type of operation - type: string - type: object - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/machine.sapcloud.io_machinesets.yaml b/config/crd/machine.sapcloud.io_machinesets.yaml deleted file mode 100644 index c569dffe..00000000 --- a/config/crd/machine.sapcloud.io_machinesets.yaml +++ /dev/null @@ -1,435 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.1 - name: machinesets.machine.sapcloud.io -spec: - group: machine.sapcloud.io - names: - kind: MachineSet - listKind: MachineSetList - plural: machinesets - shortNames: - - mcs - singular: machineset - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Number of desired replicas. - jsonPath: .spec.replicas - name: Desired - type: integer - - description: Number of actual replicas. - jsonPath: .status.replicas - name: Current - type: integer - - description: Number of ready replicas for this machine set. - jsonPath: .status.readyReplicas - name: Ready - type: integer - - description: |- - CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: MachineSet TODO - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: MachineSetSpec is the specification of a MachineSet. - properties: - machineClass: - description: ClassSpec is the class specification of machine - properties: - apiGroup: - description: API group to which it belongs - type: string - kind: - description: Kind for machine class - type: string - name: - description: Name of machine class - type: string - type: object - minReadySeconds: - format: int32 - type: integer - replicas: - format: int32 - type: integer - selector: - description: |- - A label selector is a label query over a set of resources. The result of matchLabels and - matchExpressions are ANDed. An empty label selector matches all objects. A null - label selector matches no objects. - properties: - matchExpressions: - description: matchExpressions is a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - template: - description: MachineTemplateSpec describes the data a machine should - have when created from a template - properties: - metadata: - description: |- - Standard object's metadata. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: |- - Specification of the desired behavior of the machine. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status - properties: - class: - description: Class contains the machineclass attributes of - a machine - properties: - apiGroup: - description: API group to which it belongs - type: string - kind: - description: Kind for machine class - type: string - name: - description: Name of machine class - type: string - type: object - creationTimeout: - description: MachineCreationTimeout is the timeout after which - machinie creation is declared failed. - type: string - disableHealthTimeout: - description: |- - DisableHealthTimeout if set to true, health timeout will be ignored. Leading to machine never being declared failed. - This is intended to be used only for in-place updates. - type: boolean - drainTimeout: - description: MachineDraintimeout is the timeout after which - machine is forcefully deleted. - type: string - healthTimeout: - description: MachineHealthTimeout is the timeout after which - machine is declared unhealhty/failed. - type: string - inPlaceUpdateTimeout: - description: MachineInPlaceUpdateTimeout is the timeout after - which in-place update is declared failed. - type: string - maxEvictRetries: - description: MaxEvictRetries is the number of retries that - will be attempted while draining the node. - format: int32 - type: integer - nodeConditions: - description: NodeConditions are the set of conditions if set - to true for MachineHealthTimeOut, machine will be declared - failed. - type: string - nodeTemplate: - description: NodeTemplateSpec describes the data a node should - have when created from a template - properties: - metadata: - type: object - x-kubernetes-preserve-unknown-fields: true - spec: - description: NodeSpec describes the attributes that a - node is created with. - properties: - configSource: - description: 'Deprecated: Previously used to specify - the source of the node''s configuration for the - DynamicKubeletConfig feature. This feature is removed.' - properties: - configMap: - description: ConfigMap is a reference to a Node's - ConfigMap - properties: - kubeletConfigKey: - description: |- - KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure - This field is required in all cases. - type: string - name: - description: |- - Name is the metadata.name of the referenced ConfigMap. - This field is required in all cases. - type: string - namespace: - description: |- - Namespace is the metadata.namespace of the referenced ConfigMap. - This field is required in all cases. - type: string - resourceVersion: - description: |- - ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. - This field is forbidden in Node.Spec, and required in Node.Status. - type: string - uid: - description: |- - UID is the metadata.UID of the referenced ConfigMap. - This field is forbidden in Node.Spec, and required in Node.Status. - type: string - required: - - kubeletConfigKey - - name - - namespace - type: object - type: object - externalID: - description: |- - Deprecated. Not all kubelets will set this field. Remove field after 1.13. - see: https://issues.k8s.io/61966 - type: string - podCIDR: - description: PodCIDR represents the pod IP range assigned - to the node. - type: string - podCIDRs: - description: |- - podCIDRs represents the IP ranges assigned to the node for usage by Pods on that node. If this - field is specified, the 0th entry must match the podCIDR field. It may contain at most 1 value for - each of IPv4 and IPv6. - items: - type: string - type: array - x-kubernetes-list-type: set - providerID: - description: 'ID of the node assigned by the cloud - provider in the format: ://' - type: string - taints: - description: If specified, the node's taints. - items: - description: |- - The node this Taint is attached to has the "effect" on - any pod that does not tolerate the Taint. - properties: - effect: - description: |- - Required. The effect of the taint on pods - that do not tolerate the taint. - Valid effects are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Required. The taint key to be applied - to a node. - type: string - timeAdded: - description: |- - TimeAdded represents the time at which the taint was added. - It is only written for NoExecute taints. - format: date-time - type: string - value: - description: The taint value corresponding to - the taint key. - type: string - required: - - effect - - key - type: object - type: array - x-kubernetes-list-type: atomic - unschedulable: - description: |- - Unschedulable controls node schedulability of new pods. By default, node is schedulable. - More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration - type: boolean - type: object - type: object - providerID: - description: ProviderID represents the provider's unique ID - given to a machine - type: string - type: object - type: object - type: object - status: - description: MachineSetStatus holds the most recently observed status - of MachineSet. - properties: - availableReplicas: - description: The number of available replicas (ready for at least - minReadySeconds) for this replica set. - format: int32 - type: integer - failedMachines: - description: FailedMachines has summary of machines on which lastOperation - Failed - items: - description: MachineSummary store the summary of machine. - properties: - lastOperation: - description: Last operation refers to the status of the last - operation performed - properties: - description: - description: Description of the current operation - type: string - errorCode: - description: ErrorCode of the current operation if any - type: string - lastUpdateTime: - description: Last update time of current operation - format: date-time - type: string - state: - description: State of operation - type: string - type: - description: Type of operation - type: string - type: object - name: - description: Name of the machine object - type: string - ownerRef: - description: OwnerRef - type: string - providerID: - description: ProviderID represents the provider's unique ID - given to a machine - type: string - type: object - type: array - fullyLabeledReplicas: - description: The number of pods that have labels matching the labels - of the pod template of the replicaset. - format: int32 - type: integer - lastOperation: - description: LastOperation performed - properties: - description: - description: Description of the current operation - type: string - errorCode: - description: ErrorCode of the current operation if any - type: string - lastUpdateTime: - description: Last update time of current operation - format: date-time - type: string - state: - description: State of operation - type: string - type: - description: Type of operation - type: string - type: object - machineSetCondition: - description: Represents the latest available observations of a replica - set's current state. - items: - description: MachineSetCondition describes the state of a machine - set at a certain point. - properties: - lastTransitionTime: - description: The last time the condition transitioned from one - status to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of machine set condition. - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: ObservedGeneration is the most recent generation observed - by the controller. - format: int64 - type: integer - readyReplicas: - description: The number of ready replicas for this replica set. - format: int32 - type: integer - replicas: - description: Replicas is the number of actual replicas. - format: int32 - type: integer - type: object - type: object - served: true - storage: true - subresources: - scale: - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} diff --git a/config/default/deployment.yaml b/config/default/deployment.yaml deleted file mode 100644 index d05201ee..00000000 --- a/config/default/deployment.yaml +++ /dev/null @@ -1,71 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: machine-controller-manager - namespace: default -spec: - replicas: 1 - selector: - matchLabels: - app: machine-controller-manager - template: - metadata: - labels: - app: machine-controller-manager - spec: - serviceAccountName: machine-controller-manager - containers: - - name: machine-controller-manager - image: europe-docker.pkg.dev/gardener-project/releases/gardener/machine-controller-manager:v0.60.2 - imagePullPolicy: IfNotPresent - command: - - ./machine-controller-manager - - --control-kubeconfig=inClusterConfig - - --namespace=default - - --safety-up=2 - - --safety-down=1 - - --machine-safety-overshooting-period=1m - - --v=3 - livenessProbe: - failureThreshold: 3 - httpGet: - path: /healthz - port: 10258 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - - name: machine-controller - image: localhost/machine-controller-manager-provider-stackit:0.1.0-dev - imagePullPolicy: IfNotPresent - command: - - ./machine-controller - - --control-kubeconfig=inClusterConfig - - --namespace=default - - --machine-drain-timeout=5m - - --machine-health-timeout=10m - - --machine-safety-orphan-vms-period=30m - - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure - - --v=4 - livenessProbe: - failureThreshold: 3 - httpGet: - path: /healthz - port: 10259 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - ports: - - containerPort: 10259 - name: metrics - protocol: TCP - resources: - limits: - cpu: "3" - memory: 3000Mi - requests: - cpu: 50m - memory: 64Mi diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml deleted file mode 100644 index b2ac7c08..00000000 --- a/config/default/kustomization.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: default - -resources: - - ../crd - - rbac.yaml - - deployment.yaml diff --git a/config/default/rbac.yaml b/config/default/rbac.yaml deleted file mode 100644 index 4bc0920f..00000000 --- a/config/default/rbac.yaml +++ /dev/null @@ -1,134 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: machine-controller-manager - namespace: default ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: machine-controller-manager -rules: - # Permissions for Machine CRDs - - apiGroups: - - machine.sapcloud.io - resources: - - machines - - machinesets - - machinedeployments - - machineclasses - verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch - - apiGroups: - - machine.sapcloud.io - resources: - - machines/status - - machinesets/status - - machinedeployments/status - verbs: - - get - - patch - - update - # Permissions for Nodes - - apiGroups: - - "" - resources: - - nodes - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - # Permissions for Pods (for draining) - - apiGroups: - - "" - resources: - - pods - verbs: - - get - - list - - apiGroups: - - "" - resources: - - pods/eviction - verbs: - - create - # Permissions for PVs and PVCs - - apiGroups: - - "" - resources: - - persistentvolumes - - persistentvolumeclaims - verbs: - - get - - list - - watch - # Permissions for Secrets (provider credentials and bootstrap tokens) - - apiGroups: - - "" - resources: - - secrets - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - # Permissions for Events - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch - # Permissions for Leader Election - - apiGroups: - - "" - resources: - - endpoints - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - - apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - create - - delete - - get - - list - - patch - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: machine-controller-manager -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: machine-controller-manager -subjects: - - kind: ServiceAccount - name: machine-controller-manager - namespace: default diff --git a/config/overlays/development/deployment-patches.yaml b/config/overlays/development/deployment-patches.yaml deleted file mode 100644 index 9de4bb3f..00000000 --- a/config/overlays/development/deployment-patches.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: machine-controller-manager -spec: - template: - spec: - containers: - - name: machine-controller - imagePullPolicy: Never - env: - # Development environment variables - - name: STACKIT_API_ENDPOINT - value: "https://api.stackit.cloud" - - name: STACKIT_PROJECT_ID - value: "dev-project-id" diff --git a/config/overlays/development/kustomization.yaml b/config/overlays/development/kustomization.yaml deleted file mode 100644 index c6cf1b81..00000000 --- a/config/overlays/development/kustomization.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - ../../default - -patches: - - path: deployment-patches.yaml - target: - kind: Deployment - name: machine-controller-manager diff --git a/config/overlays/e2e/deployment-patches.yaml b/config/overlays/e2e/deployment-patches.yaml deleted file mode 100644 index f95f63bf..00000000 --- a/config/overlays/e2e/deployment-patches.yaml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: machine-controller-manager -spec: - template: - spec: - containers: - # Patch machine-controller-manager container to watch machine-controller-manager namespace - - name: machine-controller-manager - command: - - ./machine-controller-manager - - --control-kubeconfig=inClusterConfig - - --namespace=machine-controller-manager - - --safety-up=2 - - --safety-down=1 - - --machine-safety-overshooting-period=1m - - --v=3 - # Patch machine-controller (provider) container - - name: machine-controller - imagePullPolicy: Never - command: - - ./machine-controller - - --control-kubeconfig=inClusterConfig - - --namespace=machine-controller-manager - - --machine-drain-timeout=5m - - --machine-health-timeout=10m - - --machine-safety-orphan-vms-period=30m - - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure - - --v=4 - env: - # E2E environment variables pointing to mock IAAS API - - name: STACKIT_API_ENDPOINT - value: "http://iaas.stackitcloud.svc.cluster.local" - - name: STACKIT_PROJECT_ID - value: "mock-project-id" - - name: STACKIT_NO_AUTH - value: "true" diff --git a/config/overlays/e2e/kustomization.yaml b/config/overlays/e2e/kustomization.yaml deleted file mode 100644 index 0a6d400a..00000000 --- a/config/overlays/e2e/kustomization.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - namespace.yaml - - ../../default - # TODO: replace ref with 'main' once changes merged upstream - - https://github.com/stackit-controllers-k8s/stackit-api-mockservers//config/apis/iaas?ref=main - - -patches: - # Patch MCM deployment to machine-controller-manager namespace - - target: - kind: Deployment - name: machine-controller-manager - patch: |- - - op: replace - path: /metadata/namespace - value: machine-controller-manager - - target: - kind: ServiceAccount - name: machine-controller-manager - patch: |- - - op: replace - path: /metadata/namespace - value: machine-controller-manager - - target: - kind: ClusterRoleBinding - name: machine-controller-manager - patch: |- - - op: replace - path: /subjects/0/namespace - value: machine-controller-manager - # Apply deployment-specific patches (env vars, commands) - - path: deployment-patches.yaml - target: - kind: Deployment - name: machine-controller-manager - # Patch iaas mock server to stackitcloud namespace - - target: - kind: Deployment - name: iaas - patch: |- - - op: replace - path: /metadata/namespace - value: stackitcloud - - target: - kind: Service - name: iaas - patch: |- - - op: replace - path: /metadata/namespace - value: stackitcloud diff --git a/config/overlays/e2e/namespace.yaml b/config/overlays/e2e/namespace.yaml deleted file mode 100644 index 3d5d13e6..00000000 --- a/config/overlays/e2e/namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: machine-controller-manager diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 00000000..2cde30fc --- /dev/null +++ b/docs/development.md @@ -0,0 +1,104 @@ +# Local Development Guide + +This guide describes how to run the STACKIT MCM provider against a real Gardener shoot on STACKIT. A local kind cluster is not suitable because the provider creates real STACKIT VMs that must join a real Kubernetes cluster. + +## Prerequisites + +Before you begin, ensure you have the following: + +- A Gardener installation on STACKIT +- A shoot cluster created in that Gardener +- Access to the seed and shoot via `gardenctl` +- A local Go toolchain + +## Overview + +You will run the provider and MCM locally while pointing them at real clusters: + +- `$TARGET_KUBECONFIG` points to the cluster where you want machines to join (the shoot). +- `$CONTROL_KUBECONFIG` points to the cluster that stores Machine objects (the seed). +- `$CONTROL_NAMESPACE` is where MCM watches Machine objects (usually `shoot--projectname--shootname` in the seed). + +MachineClass objects and Secrets are assumed to already exist. Running the provider locally results in faster feedback loops when developing new features and enables using the go debugger. + +## 1. Get kubeconfigs with gardenctl + +Assume: + +- Shoot name: `foobar` +- Seed name: `foobar-seed` + +Export kubeconfigs using `gardenctl`: + +```bash +# Target (shoot) kubeconfig +gardenctl kubeconfig --raw --shoot foobar > /tmp/target.kubeconfig + +# Control (seed) kubeconfig +gardenctl kubeconfig --raw --seed foobar-seed > /tmp/control.kubeconfig +``` + +Set these environment variables on every terminal used: + +```bash +export TARGET_KUBECONFIG=/tmp/target.kubeconfig +export CONTROL_KUBECONFIG=/tmp/control.kubeconfig +export CONTROL_NAMESPACE=shoot--testing--foobar +``` + +## 2. Scale down the in-cluster MCM + +Scale the existing MCM in the seed to 0 so your local controller can take over: + +```bash +kubectl --kubeconfig "$CONTROL_KUBECONFIG" -n "$CONTROL_NAMESPACE" scale deployment/machine-controller-manager --replicas=0 +``` + +Since Gardener periodically scales the deployment back up, you can use a watch command in a separate terminal to continuously scale it down: + +```bash +watch -n 5 "kubectl --kubeconfig '$CONTROL_KUBECONFIG' -n '$CONTROL_NAMESPACE' scale deployment/machine-controller-manager --replicas=0" +``` + +This will check and scale down the deployment every 5 seconds. +Make sure to set the environment varialbes. + +## 3. Run the provider (driver) + +On another terminal in your provider repo: + +If you are running against QA, export these environment variables before starting: + +```bash +export STACKIT_TOKEN_BASEURL="https://service-account.api.qa.stackit.cloud/token" +export STACKIT_IAAS_ENDPOINT="https://iaas.api.qa.stackit.cloud" +``` + +```bash +make start +``` + +Make sure to set the environment varialbes. + +## 4. Run MCM locally + +On another terminal in the Gardener MCM repository: + +```bash +git clone git@github.com:gardener/machine-controller-manager.git +cd machine-controller-manager +``` + +Run MCM: + +```bash +make start +``` + +Make sure to set the environment varialbes. + +## Notes + +- This workflow assumes MachineClass and Secret objects already exist and are valid. +- The local controllers should reconcile existing resources and provision STACKIT VMs that join the shoot. +- Re-enable the in-cluster MCM after testing by scaling it back up. diff --git a/docs/machine-class.md b/docs/machine-class.md index d6af3971..9b44370d 100644 --- a/docs/machine-class.md +++ b/docs/machine-class.md @@ -1,6 +1,6 @@ # MachineClass ProviderSpec -This document describes the STACKIT MachineClass ProviderSpec schema and validation rules used by the machine-controller-manager-provider-stackit. +This document describes the STACKIT MachineClass ProviderSpec schema and validation rules used by the machine-controller-manager-provider-stackit. It is generated based on the [providerSpec source code](../pkg/provider/apis/provider_spec.go). ## Overview diff --git a/pkg/client/sdk.go b/pkg/client/sdk.go index 2277fdd6..6691a690 100644 --- a/pkg/client/sdk.go +++ b/pkg/client/sdk.go @@ -84,7 +84,7 @@ func createIAASClient(serviceAccountKey string) (*iaas.APIClient, error) { // CreateServer creates a new server via STACKIT SDK // -//nolint:gocyclo // TODO: refactor +//nolint:gocyclo // this function is not complex at all func (c *SdkStackitClient) CreateServer(ctx context.Context, projectID, region string, req *CreateServerRequest) (*Server, error) { // Convert our request to SDK payload payload := &iaas.CreateServerPayload{} diff --git a/pkg/provider/apis/validation/validation.go b/pkg/provider/apis/validation/validation.go index 06c936af..67607b0e 100644 --- a/pkg/provider/apis/validation/validation.go +++ b/pkg/provider/apis/validation/validation.go @@ -48,7 +48,7 @@ var labelValueRegex = regexp.MustCompile(`^([a-zA-Z0-9]([-a-zA-Z0-9_.]*[a-zA-Z0- // ValidateProviderSpecNSecret validates provider spec and secret to check if all fields are present and valid // -//nolint:gocyclo,funlen//TODO:refactor +//nolint:gocyclo,funlen // splitting this function would make it unreadable func ValidateProviderSpecNSecret(spec *api.ProviderSpec, secrets *corev1.Secret) []error { var errors []error diff --git a/samples/deployment.yaml b/samples/deployment.yaml index b9f9cf0c..8781fa2e 100644 --- a/samples/deployment.yaml +++ b/samples/deployment.yaml @@ -12,72 +12,70 @@ spec: app: machine-controller-manager spec: containers: - - name: machine-controller-manager - # NOTE: adjust version - image: europe-docker.pkg.dev/gardener-project/releases/gardener/machine-controller-manager:v0.61.1 - imagePullPolicy: Always - command: - - ./machine-controller-manager - - --target-kubeconfig=$(TARGET_KUBECONFIG) # Mandatory Parameter - Filepath to the target cluster's kubeconfig where node objects are expected to join. - - --control-kubeconfig=$(CONTROL_KUBECONFIG) # Optional Parameter - Default value is same as target-kubeconfig - Filepath to the control cluster's kubeconfig where machine objects would be created. Optionally you could also use "inClusterConfig" when pod is running inside control kubeconfig. - - --namespace=$(CONTROL_NAMESPACE) # Optional Parameter - Default value for namespace is 'default' - The control namespace where the controller watches for it's machine objects. - - --safety-up=2 # Optional Parameter - Default value 2 - The number of excess machine objects permitted for any machineSet/machineDeployment beyond its expected number of replicas based on desired and max-surge, we call this the upper-limit. When this upper-limit is reached, the objects are frozen until the number of objects reduce. upper-limit = desired + maxSurge (if applicable) + safetyUp. - - --safety-down=1 # Optional Parameter - Default value 1 - Upper-limit minus safety-down value gives the lower-limit. This is the limits below which any temporarily frozen machineSet/machineDeployment object is unfrozen. lower-limit = desired + maxSurge (if applicable) + safetyUp - safetyDown. - - --machine-drain-timeout=5m # Optional Parameter - Timeout (in time) used while draining of machine before deletion, beyond which MCM forcefully deletes machine. - - --machine-health-timeout=10m # Optional Parameter - Default value 10mins - Timeout (in time) used while joining (during creation) or re-joining (in case of temporary health issues) of machine before it is declared as failed. - - --machine-safety-orphan-vms-period=30 # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. - - --machine-safety-overshooting-period=1 # Optional Parameter - Default value 1min - Time period (in time) used to poll for overshooting of machine objects backing a machineSet by safety controller. - - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. - - --v=3 - livenessProbe: - failureThreshold: 3 - httpGet: - path: /healthz - port: 10258 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - - command: - - ./machine-controller - - --control-kubeconfig=$(TARGET_KUBECONFIG) # Mandatory Parameter - Filepath to the target cluster's kubeconfig where node objects are expected to join. - - --target-kubeconfig=$(CONTROL_KUBECONFIG) # Optional Parameter - Default value is same as target-kubeconfig - Filepath to the control cluster's kubeconfig where machine objects would be created. Optionally you could also use "inClusterConfig" when pod is running inside control kubeconfig. - - --namespace=$(CONTROL_NAMESPACE) # Optional Parameter - Default value for namespace is 'default' - The control namespace where the controller watches for it's machine objects. - - --machine-drain-timeout=5m # Optional Parameter - Timeout (in time) used while draining of machine before deletion, beyond which MCM forcefully deletes machine. - - --machine-health-timeout=10m # Optional Parameter - Default value 10mins - Timeout (in time) used while joining (during creation) or re-joining (in case of temporary health issues) of machine before it is declared as failed. - - --machine-safety-orphan-vms-period=30m # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. - - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. - - --v=3 - # NOTE: adjust version - image: ghcr.io/stackitcloud/machine-controller-manager-provider-stackit:latest - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 3 - httpGet: - path: /healthz - port: 10259 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - name: machine-controller - ports: - - containerPort: 10259 - name: metrics - protocol: TCP - resources: - limits: - cpu: "3" - memory: 3000Mi - requests: - cpu: 50m - memory: 64Mi - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - securityContext: {} - serviceAccount: machine-controller-manager - serviceAccountName: machine-controller-manager + - name: machine-controller-manager + image: europe-docker.pkg.dev/gardener-project/releases/gardener/machine-controller-manager:v0.61.1 + imagePullPolicy: Always + command: + - ./machine-controller-manager + - --target-kubeconfig=$(TARGET_KUBECONFIG) # Mandatory Parameter - Filepath to the target cluster's kubeconfig where node objects are expected to join. + - --control-kubeconfig=$(CONTROL_KUBECONFIG) # Optional Parameter - Default value is same as target-kubeconfig - Filepath to the control cluster's kubeconfig where machine objects would be created. Optionally you could also use "inClusterConfig" when pod is running inside control kubeconfig. + - --namespace=$(CONTROL_NAMESPACE) # Optional Parameter - Default value for namespace is 'default' - The control namespace where the controller watches for it's machine objects. + - --safety-up=2 # Optional Parameter - Default value 2 - The number of excess machine objects permitted for any machineSet/machineDeployment beyond its expected number of replicas based on desired and max-surge, we call this the upper-limit. When this upper-limit is reached, the objects are frozen until the number of objects reduce. upper-limit = desired + maxSurge (if applicable) + safetyUp. + - --safety-down=1 # Optional Parameter - Default value 1 - Upper-limit minus safety-down value gives the lower-limit. This is the limits below which any temporarily frozen machineSet/machineDeployment object is unfrozen. lower-limit = desired + maxSurge (if applicable) + safetyUp - safetyDown. + - --machine-drain-timeout=5m # Optional Parameter - Timeout (in time) used while draining of machine before deletion, beyond which MCM forcefully deletes machine. + - --machine-health-timeout=10m # Optional Parameter - Default value 10mins - Timeout (in time) used while joining (during creation) or re-joining (in case of temporary health issues) of machine before it is declared as failed. + - --machine-safety-orphan-vms-period=30 # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. + - --machine-safety-overshooting-period=1 # Optional Parameter - Default value 1min - Time period (in time) used to poll for overshooting of machine objects backing a machineSet by safety controller. + - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. + - --v=3 + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10258 + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + - command: + - ./machine-controller + - --control-kubeconfig=$(TARGET_KUBECONFIG) # Mandatory Parameter - Filepath to the target cluster's kubeconfig where node objects are expected to join. + - --target-kubeconfig=$(CONTROL_KUBECONFIG) # Optional Parameter - Default value is same as target-kubeconfig - Filepath to the control cluster's kubeconfig where machine objects would be created. Optionally you could also use "inClusterConfig" when pod is running inside control kubeconfig. + - --namespace=$(CONTROL_NAMESPACE) # Optional Parameter - Default value for namespace is 'default' - The control namespace where the controller watches for it's machine objects. + - --machine-drain-timeout=5m # Optional Parameter - Timeout (in time) used while draining of machine before deletion, beyond which MCM forcefully deletes machine. + - --machine-health-timeout=10m # Optional Parameter - Default value 10mins - Timeout (in time) used while joining (during creation) or re-joining (in case of temporary health issues) of machine before it is declared as failed. + - --machine-safety-orphan-vms-period=30m # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. + - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. + - --v=3 + image: ghcr.io/stackitcloud/machine-controller-manager-provider-stackit:latest + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10259 + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + name: machine-controller + ports: + - containerPort: 10259 + name: metrics + protocol: TCP + resources: + limits: + cpu: "3" + memory: 3000Mi + requests: + cpu: 50m + memory: 64Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + securityContext: {} + serviceAccount: machine-controller-manager + serviceAccountName: machine-controller-manager dnsPolicy: ClusterFirst restartPolicy: Always From cfcec77bf0bdebfa4cb02e7b38790cf5ab412bb7 Mon Sep 17 00:00:00 2001 From: Felix Breuer Date: Tue, 17 Feb 2026 11:57:27 +0100 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: Rene Schach Co-authored-by: Robert Kaussow Co-authored-by: Marcel Boehm --- README.md | 2 +- docs/development.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a4235683..63253329 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ For detailed information on all available configuration fields, see the [Machine ## Local Testing & Development -Local development runs the provider and MCM against a real Gardener shoot on STACKIT (kind is not suitable for this provider). Follow the steps in the [local development guide](./docs/development.md). +Local development runs the provider and MCM against a real Gardener shoot on STACKIT (local kind cluster is not suitable). Follow the steps in the [local development guide](./docs/development.md). Use the Makefile targets for testing: diff --git a/docs/development.md b/docs/development.md index 2cde30fc..75434ccf 100644 --- a/docs/development.md +++ b/docs/development.md @@ -17,7 +17,7 @@ You will run the provider and MCM locally while pointing them at real clusters: - `$TARGET_KUBECONFIG` points to the cluster where you want machines to join (the shoot). - `$CONTROL_KUBECONFIG` points to the cluster that stores Machine objects (the seed). -- `$CONTROL_NAMESPACE` is where MCM watches Machine objects (usually `shoot--projectname--shootname` in the seed). +- `$CONTROL_NAMESPACE` is where MCM watches Machine objects (usually `shoot--projectname--shootname` on the seed). MachineClass objects and Secrets are assumed to already exist. Running the provider locally results in faster feedback loops when developing new features and enables using the go debugger. @@ -38,7 +38,7 @@ gardenctl kubeconfig --raw --shoot foobar > /tmp/target.kubeconfig gardenctl kubeconfig --raw --seed foobar-seed > /tmp/control.kubeconfig ``` -Set these environment variables on every terminal used: +Set these environment variables on every spun up terminal: ```bash export TARGET_KUBECONFIG=/tmp/target.kubeconfig @@ -48,7 +48,7 @@ export CONTROL_NAMESPACE=shoot--testing--foobar ## 2. Scale down the in-cluster MCM -Scale the existing MCM in the seed to 0 so your local controller can take over: +Scale the existing MCM in the seed to `0`, so your local controller can take over: ```bash kubectl --kubeconfig "$CONTROL_KUBECONFIG" -n "$CONTROL_NAMESPACE" scale deployment/machine-controller-manager --replicas=0 @@ -61,7 +61,7 @@ watch -n 5 "kubectl --kubeconfig '$CONTROL_KUBECONFIG' -n '$CONTROL_NAMESPACE' s ``` This will check and scale down the deployment every 5 seconds. -Make sure to set the environment varialbes. +Make sure to set the environment variables. ## 3. Run the provider (driver) From c0d7b7d7b65a7ded4694a48e3c5a9606ed19b718 Mon Sep 17 00:00:00 2001 From: Felix Breuer Date: Tue, 17 Feb 2026 13:39:02 +0100 Subject: [PATCH 4/5] fix review comments Signed-off-by: Felix Breuer --- LICENSE | 2 +- docs/development.md | 29 +++------ docs/machine-class.md | 6 +- docs/release-procedure.md | 7 -- samples/deployment.yaml | 130 +++++++++++++++++++------------------- 5 files changed, 79 insertions(+), 95 deletions(-) diff --git a/LICENSE b/LICENSE index 911c1037..0fe98a1f 100644 --- a/LICENSE +++ b/LICENSE @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Schwarz IT + Copyright 2025 Schwarz IT KG Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/development.md b/docs/development.md index 75434ccf..f1d85f34 100644 --- a/docs/development.md +++ b/docs/development.md @@ -23,19 +23,21 @@ MachineClass objects and Secrets are assumed to already exist. Running the provi ## 1. Get kubeconfigs with gardenctl -Assume: +Set these shell variables (replace with your values): -- Shoot name: `foobar` -- Seed name: `foobar-seed` +```bash +export SHOOT_NAME=foobar +export SEED_NAME=foobar-seed +``` Export kubeconfigs using `gardenctl`: ```bash # Target (shoot) kubeconfig -gardenctl kubeconfig --raw --shoot foobar > /tmp/target.kubeconfig +gardenctl kubeconfig --raw --shoot $SHOOT_NAME > /tmp/target.kubeconfig # Control (seed) kubeconfig -gardenctl kubeconfig --raw --seed foobar-seed > /tmp/control.kubeconfig +gardenctl kubeconfig --raw --seed $SEED_NAME > /tmp/control.kubeconfig ``` Set these environment variables on every spun up terminal: @@ -43,7 +45,7 @@ Set these environment variables on every spun up terminal: ```bash export TARGET_KUBECONFIG=/tmp/target.kubeconfig export CONTROL_KUBECONFIG=/tmp/control.kubeconfig -export CONTROL_NAMESPACE=shoot--testing--foobar +export CONTROL_NAMESPACE=shoot--testing--$SHOOT_NAME ``` ## 2. Scale down the in-cluster MCM @@ -65,21 +67,12 @@ Make sure to set the environment variables. ## 3. Run the provider (driver) -On another terminal in your provider repo: - -If you are running against QA, export these environment variables before starting: - -```bash -export STACKIT_TOKEN_BASEURL="https://service-account.api.qa.stackit.cloud/token" -export STACKIT_IAAS_ENDPOINT="https://iaas.api.qa.stackit.cloud" -``` +Set the environment varialbes from above and run another terminal in your provider repo: ```bash make start ``` -Make sure to set the environment varialbes. - ## 4. Run MCM locally On another terminal in the Gardener MCM repository: @@ -89,14 +82,12 @@ git clone git@github.com:gardener/machine-controller-manager.git cd machine-controller-manager ``` -Run MCM: +Set the environment varialbes from above and run the MCM: ```bash make start ``` -Make sure to set the environment varialbes. - ## Notes - This workflow assumes MachineClass and Secret objects already exist and are valid. diff --git a/docs/machine-class.md b/docs/machine-class.md index 9b44370d..b9ec2dd8 100644 --- a/docs/machine-class.md +++ b/docs/machine-class.md @@ -1,6 +1,6 @@ # MachineClass ProviderSpec -This document describes the STACKIT MachineClass ProviderSpec schema and validation rules used by the machine-controller-manager-provider-stackit. It is generated based on the [providerSpec source code](../pkg/provider/apis/provider_spec.go). +This document describes the STACKIT MachineClass ProviderSpec schema and validation rules used by the machine-controller-manager-provider-stackit. It is AI generated based on the [providerSpec source code](../pkg/provider/apis/provider_spec.go). ## Overview @@ -8,8 +8,8 @@ A MachineClass defines how STACKIT servers should be created. The ProviderSpec i ## Required Fields -- `region` (string): STACKIT region such as "eu01" or "eu02". -- `machineType` (string): STACKIT server type such as "c2i.2" or "m2i.8". +- `region` (string): STACKIT region, such as "eu01" or "eu02". +- `machineType` (string): STACKIT server type, such as "c2i.2" or "m2i.8". - `imageId` (string): UUID of the image to boot from, unless `bootVolume.source` is set. - `networking` (object): Must be set and must specify either `networkId` or `nicIds`. diff --git a/docs/release-procedure.md b/docs/release-procedure.md index ca33a471..822adf18 100644 --- a/docs/release-procedure.md +++ b/docs/release-procedure.md @@ -1,12 +1,5 @@ # Release Procedure -## Table of Contents - -- [Overview](#overview) -- [General Information](#general-information) -- [Automated Release Process (Primary Method)](#automated-release-process-primary-method) -- [Manual Release Process (Fallback Method)](#manual-release-process-fallback-method) - ## Overview This document outlines the standard procedure for creating new releases of the STACKIT machine-controller-manager. diff --git a/samples/deployment.yaml b/samples/deployment.yaml index 8781fa2e..08d3b87c 100644 --- a/samples/deployment.yaml +++ b/samples/deployment.yaml @@ -12,70 +12,70 @@ spec: app: machine-controller-manager spec: containers: - - name: machine-controller-manager - image: europe-docker.pkg.dev/gardener-project/releases/gardener/machine-controller-manager:v0.61.1 - imagePullPolicy: Always - command: - - ./machine-controller-manager - - --target-kubeconfig=$(TARGET_KUBECONFIG) # Mandatory Parameter - Filepath to the target cluster's kubeconfig where node objects are expected to join. - - --control-kubeconfig=$(CONTROL_KUBECONFIG) # Optional Parameter - Default value is same as target-kubeconfig - Filepath to the control cluster's kubeconfig where machine objects would be created. Optionally you could also use "inClusterConfig" when pod is running inside control kubeconfig. - - --namespace=$(CONTROL_NAMESPACE) # Optional Parameter - Default value for namespace is 'default' - The control namespace where the controller watches for it's machine objects. - - --safety-up=2 # Optional Parameter - Default value 2 - The number of excess machine objects permitted for any machineSet/machineDeployment beyond its expected number of replicas based on desired and max-surge, we call this the upper-limit. When this upper-limit is reached, the objects are frozen until the number of objects reduce. upper-limit = desired + maxSurge (if applicable) + safetyUp. - - --safety-down=1 # Optional Parameter - Default value 1 - Upper-limit minus safety-down value gives the lower-limit. This is the limits below which any temporarily frozen machineSet/machineDeployment object is unfrozen. lower-limit = desired + maxSurge (if applicable) + safetyUp - safetyDown. - - --machine-drain-timeout=5m # Optional Parameter - Timeout (in time) used while draining of machine before deletion, beyond which MCM forcefully deletes machine. - - --machine-health-timeout=10m # Optional Parameter - Default value 10mins - Timeout (in time) used while joining (during creation) or re-joining (in case of temporary health issues) of machine before it is declared as failed. - - --machine-safety-orphan-vms-period=30 # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. - - --machine-safety-overshooting-period=1 # Optional Parameter - Default value 1min - Time period (in time) used to poll for overshooting of machine objects backing a machineSet by safety controller. - - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. - - --v=3 - livenessProbe: - failureThreshold: 3 - httpGet: - path: /healthz - port: 10258 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - - command: - - ./machine-controller - - --control-kubeconfig=$(TARGET_KUBECONFIG) # Mandatory Parameter - Filepath to the target cluster's kubeconfig where node objects are expected to join. - - --target-kubeconfig=$(CONTROL_KUBECONFIG) # Optional Parameter - Default value is same as target-kubeconfig - Filepath to the control cluster's kubeconfig where machine objects would be created. Optionally you could also use "inClusterConfig" when pod is running inside control kubeconfig. - - --namespace=$(CONTROL_NAMESPACE) # Optional Parameter - Default value for namespace is 'default' - The control namespace where the controller watches for it's machine objects. - - --machine-drain-timeout=5m # Optional Parameter - Timeout (in time) used while draining of machine before deletion, beyond which MCM forcefully deletes machine. - - --machine-health-timeout=10m # Optional Parameter - Default value 10mins - Timeout (in time) used while joining (during creation) or re-joining (in case of temporary health issues) of machine before it is declared as failed. - - --machine-safety-orphan-vms-period=30m # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. - - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. - - --v=3 - image: ghcr.io/stackitcloud/machine-controller-manager-provider-stackit:latest - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 3 - httpGet: - path: /healthz - port: 10259 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - name: machine-controller - ports: - - containerPort: 10259 - name: metrics - protocol: TCP - resources: - limits: - cpu: "3" - memory: 3000Mi - requests: - cpu: 50m - memory: 64Mi - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - securityContext: {} - serviceAccount: machine-controller-manager - serviceAccountName: machine-controller-manager + - name: machine-controller-manager + image: europe-docker.pkg.dev/gardener-project/releases/gardener/machine-controller-manager:v0.61.1 + imagePullPolicy: Always + command: + - ./machine-controller-manager + - --target-kubeconfig=$(TARGET_KUBECONFIG) # Mandatory Parameter - Filepath to the target cluster's kubeconfig where node objects are expected to join. + - --control-kubeconfig=$(CONTROL_KUBECONFIG) # Optional Parameter - Default value is same as target-kubeconfig - Filepath to the control cluster's kubeconfig where machine objects would be created. Optionally you could also use "inClusterConfig" when pod is running inside control kubeconfig. + - --namespace=$(CONTROL_NAMESPACE) # Optional Parameter - Default value for namespace is 'default' - The control namespace where the controller watches for it's machine objects. + - --safety-up=2 # Optional Parameter - Default value 2 - The number of excess machine objects permitted for any machineSet/machineDeployment beyond its expected number of replicas based on desired and max-surge, we call this the upper-limit. When this upper-limit is reached, the objects are frozen until the number of objects reduce. upper-limit = desired + maxSurge (if applicable) + safetyUp. + - --safety-down=1 # Optional Parameter - Default value 1 - Upper-limit minus safety-down value gives the lower-limit. This is the limits below which any temporarily frozen machineSet/machineDeployment object is unfrozen. lower-limit = desired + maxSurge (if applicable) + safetyUp - safetyDown. + - --machine-drain-timeout=5m # Optional Parameter - Timeout (in time) used while draining of machine before deletion, beyond which MCM forcefully deletes machine. + - --machine-health-timeout=10m # Optional Parameter - Default value 10mins - Timeout (in time) used while joining (during creation) or re-joining (in case of temporary health issues) of machine before it is declared as failed. + - --machine-safety-orphan-vms-period=30 # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. + - --machine-safety-overshooting-period=1 # Optional Parameter - Default value 1min - Time period (in time) used to poll for overshooting of machine objects backing a machineSet by safety controller. + - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. + - --v=3 + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10258 + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + - command: + - ./machine-controller + - --control-kubeconfig=$(TARGET_KUBECONFIG) # Mandatory Parameter - Filepath to the target cluster's kubeconfig where node objects are expected to join. + - --target-kubeconfig=$(CONTROL_KUBECONFIG) # Optional Parameter - Default value is same as target-kubeconfig - Filepath to the control cluster's kubeconfig where machine objects would be created. Optionally you could also use "inClusterConfig" when pod is running inside control kubeconfig. + - --namespace=$(CONTROL_NAMESPACE) # Optional Parameter - Default value for namespace is 'default' - The control namespace where the controller watches for it's machine objects. + - --machine-drain-timeout=5m # Optional Parameter - Timeout (in time) used while draining of machine before deletion, beyond which MCM forcefully deletes machine. + - --machine-health-timeout=10m # Optional Parameter - Default value 10mins - Timeout (in time) used while joining (during creation) or re-joining (in case of temporary health issues) of machine before it is declared as failed. + - --machine-safety-orphan-vms-period=30m # Optional Parameter - Default value 30mins - Time period (in time) used to poll for orphan VMs by safety controller. + - --node-conditions=ReadonlyFilesystem,KernelDeadlock,DiskPressure # List of comma-separated/case-sensitive node-conditions which when set to True will change machine to a failed state after MachineHealthTimeout duration. It may further be replaced with a new machine if the machine is backed by a machine-set object. + - --v=3 + image: ghcr.io/stackitcloud/machine-controller-manager-provider-stackit:latest + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 10259 + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 5 + name: machine-controller + ports: + - containerPort: 10259 + name: metrics + protocol: TCP + resources: + limits: + cpu: "3" + memory: 3000Mi + requests: + cpu: 50m + memory: 64Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + securityContext: {} + serviceAccount: machine-controller-manager + serviceAccountName: machine-controller-manager dnsPolicy: ClusterFirst restartPolicy: Always From 90037b9dc4f2001ca069a7ffca5f4b8a1ae025f9 Mon Sep 17 00:00:00 2001 From: Felix Breuer Date: Tue, 17 Feb 2026 14:23:38 +0100 Subject: [PATCH 5/5] update release procedure Signed-off-by: Felix Breuer --- docs/release-procedure.md | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/docs/release-procedure.md b/docs/release-procedure.md index 822adf18..e6898f46 100644 --- a/docs/release-procedure.md +++ b/docs/release-procedure.md @@ -24,25 +24,16 @@ Publishing the release automatically creates the corresponding Git tag (e.g., `v ## Manual Release Process (Fallback Method) -If the `release-tool` or its associated Prow job fails, you can manually trigger a release by creating and pushing a Git tag from the appropriate release branch. +If the `release-tool` or its associated Prow job fails, use the GitHub web UI to create and publish a release: -1. **Check out the release branch:** Ensure you have the latest changes from the correct release branch. +1. Go to the repository on GitHub and click **Releases** on the right side, then click **Draft new release**. - ```bash - git checkout main - git pull origin main - ``` +2. Open the **Select tag** dropdown and choose **Create new tag** at the bottom. Enter the new tag name (for example `v2.1.0`) and pick the target branch/commit, then confirm. -2. **Create the Git tag:** Create a new, annotated tag for the release, following semantic versioning. +3. Click **Generate release notes** to let GitHub populate the changelog. - ```bash - git tag v2.1.0 - ``` +4. In the release description, add a line `Released by @` to indicate the publisher. -3. **Push the tag to the remote repository:** +5. Click **Publish release** to create the release. - ```bash - git push origin v2.1.0 - ``` - -Pushing a tag that starts with `v` (e.g., `v2.1.0`) automatically triggers the same Prow release job that builds and publishes the final container images. You may need to manually update the release notes on GitHub afterward. +Publishing a new release triggers the same Prow release job that builds and publishes the final container images.