mirror of
https://github.com/clastix/kamaji.git
synced 2026-02-23 06:13:51 +00:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a160cdb74 | ||
|
|
9688d288b7 | ||
|
|
87c7c984de | ||
|
|
e5cccfe88b | ||
|
|
197518b0b4 | ||
|
|
7ac8e5e539 | ||
|
|
cec4f9136d | ||
|
|
4299b72d7f | ||
|
|
eff68db336 | ||
|
|
74a6eb6b80 | ||
|
|
21fe27935f | ||
|
|
e3a8ff90da | ||
|
|
8e6cea2d2d | ||
|
|
1c90a4f333 | ||
|
|
6123d9a5a4 | ||
|
|
587d3bb24e | ||
|
|
4465bd8449 | ||
|
|
cf1f2763f6 | ||
|
|
25dc19f839 | ||
|
|
1ccc1d1b1e | ||
|
|
1d96710890 | ||
|
|
edceda3302 | ||
|
|
755cc5bacd | ||
|
|
e0c86d685c | ||
|
|
ddb700f4f0 | ||
|
|
4bdddfc695 | ||
|
|
8b999f1323 | ||
|
|
2571086ff3 | ||
|
|
cd9d92296b | ||
|
|
f24ff618a9 | ||
|
|
4bf39149ec | ||
|
|
045c5bbd7c | ||
|
|
6eb3171817 | ||
|
|
289bad540c | ||
|
|
ac06447706 | ||
|
|
95de31d697 | ||
|
|
0037b4941c | ||
|
|
c251f57f06 | ||
|
|
129cb0e6fe | ||
|
|
73e0618ad3 | ||
|
|
6c2634b5e9 | ||
|
|
dac670113f | ||
|
|
c8039cdf5c | ||
|
|
a7cfc9a898 | ||
|
|
0f1a4f28de | ||
|
|
40f57466e2 |
6
.github/workflows/ci.yaml
vendored
6
.github/workflows/ci.yaml
vendored
@@ -14,12 +14,12 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.19'
|
||||
go-version: '1.21'
|
||||
check-latest: true
|
||||
- name: Run golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3.2.0
|
||||
with:
|
||||
version: v1.49.0
|
||||
version: v1.54.2
|
||||
only-new-issues: false
|
||||
args: --timeout 5m --config .golangci.yml
|
||||
diff:
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.19'
|
||||
go-version: '1.21'
|
||||
check-latest: true
|
||||
- run: make yaml-installation-file
|
||||
- name: Checking if YAML installer file is not aligned
|
||||
|
||||
2
.github/workflows/e2e.yaml
vendored
2
.github/workflows/e2e.yaml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.19'
|
||||
go-version: '1.21'
|
||||
check-latest: true
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
|
||||
@@ -11,6 +11,7 @@ linters-settings:
|
||||
|
||||
linters:
|
||||
disable:
|
||||
- depguard
|
||||
- wrapcheck
|
||||
- gomnd
|
||||
- scopelint
|
||||
|
||||
21
ADOPTERS.md
Normal file
21
ADOPTERS.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Adopters
|
||||
|
||||
This is a list of companies that have adopted Kamaji.
|
||||
Feel free to open a Pull-Request to get yours listed.
|
||||
|
||||
### Adopter list (alphabetically)
|
||||
|
||||
| Type | Name | Since | Website | Use-Case |
|
||||
|:-|:-|:-|:-|:-|
|
||||
| End-user | KINX | 2024 | [link](https://kinx.net/?lang=en) | KINX is an Internet infrastructure service provider and will use kamaji for its new [Managed Kubernetes Service](https://kinx.net/service/cloud/kubernetes/intro/?lang=en). |
|
||||
| End-user | sevensphere | 2023 | [link](https://www.sevensphere.io) | Sevensphere provides consulting services for end-user companies / cloud providers and uses Kamaji for designing cloud/on-premises Kubernetes-as-a-Service platform. |
|
||||
| Vendor | Ænix | 2023 | [link](https://aenix.io/) | Ænix provides consulting services for cloud providers and uses Kamaji for running Kubernetes-as-a-Service in free PaaS platform [Cozystack](https://cozystack.io). |
|
||||
| Vendor | Netsons | 2023 | [link](https://www.netsons.com) | Netsons is an Italian hosting and cloud provider and uses Kamaji in its [Managed Kubernetes](https://www.netsons.com/kubernetes) offering. |
|
||||
|
||||
### Adopter Types
|
||||
|
||||
**End-user**: The organization runs Kamaji in production in some way.
|
||||
|
||||
**Integration**: The organization has a product that integrates with Kamaji, but does not contain Kamaji.
|
||||
|
||||
**Vendor**: The organization packages Kamaji in their product and sells it as part of their product.
|
||||
@@ -1,5 +1,5 @@
|
||||
# Build the manager binary
|
||||
FROM golang:1.19 as builder
|
||||
FROM golang:1.21 as builder
|
||||
|
||||
WORKDIR /workspace
|
||||
# Copy the Go Modules manifests
|
||||
|
||||
4
Makefile
4
Makefile
@@ -3,7 +3,7 @@
|
||||
# To re-generate a bundle for another specific version without changing the standard setup, you can:
|
||||
# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
|
||||
# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
|
||||
VERSION ?= 0.3.4
|
||||
VERSION ?= 0.4.2
|
||||
|
||||
# CHANNELS define the bundle channels used in the bundle.
|
||||
# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
|
||||
@@ -89,7 +89,7 @@ controller-gen: ## Download controller-gen locally if necessary.
|
||||
|
||||
GOLANGCI_LINT = $(shell pwd)/bin/golangci-lint
|
||||
golangci-lint: ## Download golangci-lint locally if necessary.
|
||||
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint@v1.49.0)
|
||||
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2)
|
||||
|
||||
KUSTOMIZE = $(shell pwd)/bin/kustomize
|
||||
kustomize: ## Download kustomize locally if necessary.
|
||||
|
||||
151
README.md
151
README.md
@@ -3,45 +3,158 @@
|
||||
<p align="left">
|
||||
<img src="https://img.shields.io/github/license/clastix/kamaji"/>
|
||||
<img src="https://img.shields.io/github/go-mod/go-version/clastix/kamaji"/>
|
||||
<a href="https://github.com/clastix/kamaji/releases">
|
||||
<img src="https://img.shields.io/github/v/release/clastix/kamaji"/>
|
||||
<img src="https://goreportcard.com/badge/github.com/clastix/kamaji">
|
||||
</a>
|
||||
<a href="https://github.com/clastix/kamaji/releases"><img src="https://img.shields.io/github/v/release/clastix/kamaji"/></a>
|
||||
<img src="https://goreportcard.com/badge/github.com/clastix/kamaji">
|
||||
<a href="https://kubernetes.slack.com/archives/C03GLTTMWNN"><img alt="#kamaji on Kubernetes Slack" src="https://img.shields.io/badge/slack-@kubernetes/kamaji-blue.svg?logo=slack"/></a>
|
||||
</p>
|
||||
|
||||

|
||||

|
||||
|
||||
**Kamaji** is a **Kubernetes Control Plane Manager**. It operates Kubernetes at scale with a fraction of the operational burden. Kamaji is special because the Control Plane components are running inside pods instead of dedicated machines. This solution makes running multiple Control Planes cheaper and easier to deploy and operate.
|
||||
### 🤔 What is Kamaji?
|
||||
|
||||
<img src="docs/content/images/architecture.png" width="600">
|
||||
**Kamaji** is a **Kubernetes Control Plane Manager** leveraging on the concept of [**Hosted Control Plane**](https://clastix.io/post/the-raise-of-hosted-control-plane-in-kubernetes/).
|
||||
|
||||
## Main Features
|
||||
Kamaji's approach is based on running the Kubernetes Control Plane components in Pods instead of dedicated machines.
|
||||
This allows operating Kubernetes clusters at scale, with a fraction of the operational burden.
|
||||
Thanks to this approach, running multiple Control Planes can be cheaper and easier to deploy and operate.
|
||||
|
||||
- **Multi-cluster Management:** centrally manage multiple Kubernetes clusters from a single Management Cluster.
|
||||
_Kamaji is like a fleet of Site Reliability Engineers with expertise codified into its logic, working 24/7 to keep up and running your Control Planes._
|
||||
|
||||
<img src="docs/content/images/architecture.png" width="600" style="display: block; margin: 0 auto">
|
||||
|
||||
### 📖 How it works
|
||||
|
||||
Kamaji is extending the Kubernetes API capabilities thanks to [Custom Resource Definitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions).
|
||||
|
||||
By installing Kamaji, two pairs of new APIs will be available:
|
||||
|
||||
- `TenantControlPlane`, the instance definition of your desired Kubernetes Control Plane
|
||||
- `Datastore`, the backing store used by one (or more) `TenantControlPlane`
|
||||
|
||||
The `TenantControlPlane` (short-named as `tcp`) objects are Namespace-scoped and allows configuring every aspect of your desired Control Plane.
|
||||
Besides the Kubernetes configuration values, you can specify the Pod options such as limit, request, tolerations, node selector, etc.,
|
||||
as well as how these should be exposed (e.g.: using a `ClusterIP`, a `LoadBalancer`, or a `NodePort`).
|
||||
|
||||
The `TenantControlPlane` is the stateless definition of the Control Plane allowing to set up the required components for a full-fledged Kubernetest cluster.
|
||||
The state is managed by the `Datastore` API, a cluster-scoped resource which can hold the data of one or more Kubernetes clusters.
|
||||
|
||||
> For further information about the API specifications and all the available options,
|
||||
> refer to the official [API reference](https://kamaji.clastix.io/reference/api/#tenantcontrolplane).
|
||||
|
||||
### ⭐️ Main features
|
||||
|
||||
- **Fast provisioning time**: depending on the infrastructure, Tenant Control Planes are up and ready to serve traffic in **16 seconds**.
|
||||
- **Streamlined update**: the rollout to a new Kubernetes version for a given Tenant Control Plane takes just **10 seconds**, with a Blue/Green deployment to avoid serving mixed Kubernetes versions.
|
||||
- **Resource optimization**: thanks to the Datastore decoupling, there's no need of odd number instances (e.g.: RAFT consensus) by allowing to save up to 60% of HW resources.
|
||||
- **Scale from zero to the moon**: scale down the instance when there's no usage, or automatically scale to support the traffic spikes reusing the Kubernetes patterns.
|
||||
- **Declarative approach, constant reconciliation**: thanks to the Operator pattern, drift detection happens in real-time, maintaining the desired state.
|
||||
- **Automated certificates management**: Kamaji leverages on `kubeadm` and the certificates are automatically created and rotated for you.
|
||||
- **Managing core addons**: Kamaji allows configuring automatically `kube-proxy`, `CoreDNS`, and `konnectivity`, with automatic remediation in case of user errors (e.g.: deleting the `CoreDNS` deployment).
|
||||
- **Auto Healing**: the `TenantControlPlane` objects in the management cluster are tracked by Kamaji, in case of deletion of those, everything is created in an idempotent way.
|
||||
- **Datastore multi-tenancy**: optionally, Kamaji allows running multiple Control Planes on the same _Datastore_ instance leveraging on the multi-tenancy of each driver, decreasing operations and optimizing costs.
|
||||
- **Overcoming `etcd` limitations**: optionally, Kamaji allows using a different _Datastore_ thanks to [`kine`](https://github.com/k3s-io/kine) by supporting `MySQL` or `PostgreSQL` as an alternative.
|
||||
- **Simplifying mixed-networks setup**: thanks to [`Konnectivity`](https://kubernetes.io/docs/tasks/extend-kubernetes/setup-konnectivity/),
|
||||
the Tenant Control Plane is connected to the worker nodes hosted in a different network, overcoming the no-NAT availability when dealing with nodes with a non routable IP address
|
||||
(e.g.: worker nodes in a different infrastructure).
|
||||
|
||||
### 🚀 Use cases
|
||||
|
||||
- [**Creating a private Managed Kubernetes Service**](https://clastix.io/post/netsons-builds-a-managed-kubernetes-service-with-kamaji-and-open-stack/)
|
||||
- [**Building a Platform as a Service**](https://aenix.io/cozystack/)
|
||||
- [**Overcoming public Managed Kubernetes Services**](https://clastix.io/post/overcoming-eks-limitations-with-kamaji-on-aws/) such as EKS
|
||||
- [**Hybrid infrastructures**](https://clastix.io/post/bridging-the-gap-hybrid-kubernetes-clusters-with-remote-control-planes/):
|
||||
host the Control Plane on the Cloud and worker nodes on prem or vice-versa, according to your needs.
|
||||
- [**Kubernetes at the edge**](https://clastix.io/post/edgevolution-unleashing-the-power-of-kubernetes-clusters-for-a-revolutionary-edge-computing-experience/):
|
||||
take full advantage of the _Kubernetes API Server as a service_ paradigm.
|
||||
- **Kubernetes Control Plane as a Service:** centrally manage multiple Kubernetes clusters from a single management point (_Multi-Cluster management_).
|
||||
- **High-density Control Plane:** place multiple control planes on the same infrastructure, instead of having dedicated machines for each control plane.
|
||||
- **Strong Multi-tenancy:** leave users to access the control plane with admin permissions while keeping them isolated at the infrastructure level.
|
||||
- **Kubernetes Inception:** use Kubernetes to manage Kubernetes with automation, high-availability, fault tolerance, and autoscaling out of the box.
|
||||
- **Bring Your Own Device:** keep the control plane isolated from data plane. Worke nodes can join and run consistently everywhere: cloud, edge, and data-center.
|
||||
- **Bring Your Own Device:** keep the control plane isolated from data plane. Worker nodes can join and run consistently from everywhere: cloud, edge, and data-center.
|
||||
- **Full CNCF compliant:** all clusters are built with upstream Kubernetes binaries, resulting in full CNCF compliant Kubernetes clusters.
|
||||
|
||||
## Roadmap
|
||||
> 🤔 You'd like to do the same but don't know how?
|
||||
> 💡 [CLASTIX](https://clastix.io/) can help you with your needs!
|
||||
|
||||
### 🧑💻 Production grade
|
||||
|
||||
Kamaji is empowering several businesses, and it counts public adopters.
|
||||
Check out the [adopters](./ADOPTERS.md) file to learn more.
|
||||
|
||||
> 🤗 If you're using Kamaji, share your love by opening a PR!
|
||||
|
||||
### 🍦 Vanilla Kubernetes clusters
|
||||
|
||||
Kamaji is **not** yet-another-Kubernetes distribution: you have full freedom on the technology stack to provide to end users.
|
||||
Kamaji is a perfect fit for Platform Engineering, hiding the complexity of the Control Plane management to developers and DevOps engineers.
|
||||
|
||||
The provided Kubernetes Control Planes are [CNCF compliant clusters](https://kamaji.clastix.io/reference/conformance/).
|
||||
|
||||
<img src="https://raw.githubusercontent.com/cncf/artwork/master/projects/kubernetes/certified-kubernetes/versionless/color/certified-kubernetes-color.png" style="display: block; width: 75px; margin: 0 auto">
|
||||
|
||||
### 🐢 Cluster API support
|
||||
|
||||
Kamaji is **not** a [Cluster API](https://cluster-api.sigs.k8s.io/) replacement, rather, it plays very well with it.
|
||||
|
||||
Since Kamaji is just focusing on the Control Plane a [Kamaji's Cluster API Control Plane provider](https://github.com/clastix/cluster-api-control-plane-provider-kamaji) has been developed.
|
||||
|
||||
### 🛣️ Roadmap
|
||||
|
||||
- [x] Dynamic address on Load Balancer
|
||||
- [x] Zero Downtime Tenant Control Plane upgrade
|
||||
- [x] Join worker nodes from anywhere
|
||||
- [x] Alternative datastore MySQL and PostgreSQL
|
||||
- [x] Pool of multiple datastores
|
||||
- [x] Seamless migration between datastores
|
||||
- [x] [Join worker nodes from anywhere thanks to Konnectivity](https://kamaji.clastix.io/concepts/#konnectivity)
|
||||
- [x] [Alternative datastore MySQL and PostgreSQL](https://kamaji.clastix.io/guides/alternative-datastore/)
|
||||
- [x] [Pool of multiple datastores](https://kamaji.clastix.io/concepts/#datastores)
|
||||
- [x] [Seamless migration between datastores](https://kamaji.clastix.io/guides/datastore-migration/)
|
||||
- [ ] Automatic assignment to a datastore
|
||||
- [ ] Autoscaling of Tenant Control Plane
|
||||
- [x] Provisioning through Cluster APIs
|
||||
- [x] [Provisioning through Cluster APIs](https://github.com/clastix/cluster-api-control-plane-provider-kamaji)
|
||||
- [ ] Terraform provider
|
||||
- [ ] Custom Prometheus metrics
|
||||
|
||||
### 🎥 Multimedia
|
||||
|
||||
## Documentation
|
||||
Please, check the project's [documentation](https://kamaji.clastix.io/) for getting started with Kamaji.
|
||||
- Playlist ▶️ [Tutorials and How-Tos by Dario Tranchitella, CLASTIX](https://www.youtube.com/playlist?list=PLjiUjoV4Ws_3pNsUpTXI-KKk731nD2MQY)
|
||||
- YouTube ▶️ [Metal³ provisioning with Kamaji Hosted Control Planes by Huy Mai, Ericsson](https://youtu.be/u9sbURj6jXY?t=10536)
|
||||
- YouTube ▶️ [Hands-on introduction to Kamaji](https://www.youtube.com/watch?v=HhevxwQWQ88)
|
||||
- YouTube ▶️ [Scaling Kubernetes up to 1,000 Control Planes](https://www.youtube.com/watch?v=W_HXRXJh96U)
|
||||
- YouTube ▶️ [Equinix, Kamaji, and Cluster API](https://www.youtube.com/watch?v=TLBTqROj_wA)
|
||||
- YouTube ▶️ [Rancher & Kamaji: solving multitenancy challenges in the Kubernetes world](https://www.youtube.com/watch?v=VXHNrMmlF8U)
|
||||
- YouTube ▶️ [Enabling Self-Service Kubernetes clusters with Kamaji and Paralus](https://www.youtube.com/watch?v=JWA2LwZazM0)
|
||||
|
||||
## Contributions
|
||||
Kamaji is Open Source with Apache 2 license and any contribution is welcome. Open an issue or suggest an enhancement on the GitHub [project's page](https://github.com/clastix/kamaji). Join the [Kubernetes Slack Workspace](https://slack.k8s.io/) and the [`#kamaji`](https://kubernetes.slack.com/archives/C03GLTTMWNN) channel to meet end-users and contributors.
|
||||
### 🏷️ Versioning
|
||||
|
||||
Versioning adheres to the [Semantic Versioning](http://semver.org/) principles.
|
||||
A full list of the available releases is available in the GitHub repository's [**Release** section](https://github.com/clastix/kamaji/releases).
|
||||
|
||||
### 📄 Documentation
|
||||
|
||||
Further documentation can be found on the official [Kamaji documentation website](https://kamaji.clastix.io/).
|
||||
|
||||
### 🤝 Contributions
|
||||
|
||||
Contributions are highly appreciated and very welcomed!
|
||||
|
||||
In case of bugs, please, check if the issue has been already opened by checking the [GitHub Issues](https://github.com/clastix/kamaji/issues) section.
|
||||
In case it isn't, you can open a new one: a detailed report will help us to replicate it, assess it, and work on a fix.
|
||||
|
||||
You can express your intention in working on the fix on your own.
|
||||
The commit messages are checked according to the described [semantics](https://github.com/projectcapsule/capsule/blob/main/CONTRIBUTING.md#semantics).
|
||||
Commits are used to generate the changelog, and their author will be referenced in it.
|
||||
|
||||
In case of **✨ Feature Requests** please use the [Discussion's Feature Request section](https://github.com/clastix/kamaji/discussions/categories/feature-requests).
|
||||
|
||||
### 📝 License
|
||||
|
||||
The Kamaji Cluster API Control Plane provider is licensed under Apache 2.0.
|
||||
The code is provided as-is with no warranties.
|
||||
|
||||
### 🛟 Commercial Support
|
||||
|
||||
 [CLASTIX](https://clastix.io/) is the commercial company behind Kamaji and the Cluster API Control Plane provider.
|
||||
|
||||
If you're looking to run Kamaji in production and would like to learn more, **CLASTIX** can help by offering [Open Source support plans](https://clastix.io/support),
|
||||
as well as providing a comprehensive Enterprise Platform named [CLASTIX Enterprise Platform](https://clastix.cloud/), built on top of the Kamaji and [Capsule](https://capsule.clastix.io/) project (now donated to CNCF as a Sandbox project).
|
||||
|
||||
Feel free to get in touch with the provided [Contact form](https://clastix.io/contact).
|
||||
@@ -138,7 +138,9 @@ type DeploymentSpec struct {
|
||||
// (kube-apiserver, controller-manager, and scheduler).
|
||||
Resources *ControlPlaneComponentsResources `json:"resources,omitempty"`
|
||||
// ExtraArgs allows adding additional arguments to the Control Plane components,
|
||||
// such as kube-apiserver, controller-manager, and scheduler.
|
||||
// such as kube-apiserver, controller-manager, and scheduler. WARNING - This option
|
||||
// can override existing parameters and cause components to misbehave in unxpected ways.
|
||||
// Only modify if you know what you are doing.
|
||||
ExtraArgs *ControlPlaneExtraArgs `json:"extraArgs,omitempty"`
|
||||
AdditionalMetadata AdditionalMetadata `json:"additionalMetadata,omitempty"`
|
||||
// AdditionalInitContainers allows adding additional init containers to the Control Plane deployment.
|
||||
@@ -189,6 +191,9 @@ type ImageOverrideTrait struct {
|
||||
}
|
||||
|
||||
// ExtraArgs allows adding additional arguments to said component.
|
||||
// WARNING - This option can override existing konnectivity
|
||||
// parameters and cause konnectivity components to misbehave in
|
||||
// unxpected ways. Only modify if you know what you are doing.
|
||||
type ExtraArgs []string
|
||||
|
||||
type KonnectivityServerSpec struct {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
apiVersion: v2
|
||||
appVersion: v0.3.4
|
||||
appVersion: v0.4.2
|
||||
description: Kamaji is a Kubernetes Control Plane Manager.
|
||||
home: https://github.com/clastix/kamaji
|
||||
icon: https://github.com/clastix/kamaji/raw/master/assets/logo-colored.png
|
||||
@@ -15,8 +15,8 @@ name: kamaji
|
||||
sources:
|
||||
- https://github.com/clastix/kamaji
|
||||
type: application
|
||||
version: 0.12.5
|
||||
version: 0.15.1
|
||||
annotations:
|
||||
catalog.cattle.io/certified: partner
|
||||
catalog.cattle.io/release-name: kamaji
|
||||
catalog.cattle.io/display-name: Kamaji
|
||||
catalog.cattle.io/display-name: Kamaji
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# kamaji
|
||||
|
||||
  
|
||||
  
|
||||
|
||||
Kamaji is a Kubernetes Control Plane Manager.
|
||||
|
||||
@@ -66,6 +66,8 @@ Here the values you can override:
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| affinity | object | `{}` | Kubernetes affinity rules to apply to Kamaji controller pods |
|
||||
| cfssl.image.repository | string | `"cfssl/cfssl"` | |
|
||||
| cfssl.image.tag | string | `"latest"` | |
|
||||
| datastore.basicAuth.passwordSecret.keyPath | string | `nil` | The Secret key where the data is stored. |
|
||||
| datastore.basicAuth.passwordSecret.name | string | `nil` | The name of the Secret containing the password used to connect to the relational database. |
|
||||
| datastore.basicAuth.passwordSecret.namespace | string | `nil` | The namespace of the Secret containing the password used to connect to the relational database. |
|
||||
@@ -73,8 +75,9 @@ Here the values you can override:
|
||||
| datastore.basicAuth.usernameSecret.name | string | `nil` | The name of the Secret containing the username used to connect to the relational database. |
|
||||
| datastore.basicAuth.usernameSecret.namespace | string | `nil` | The namespace of the Secret containing the username used to connect to the relational database. |
|
||||
| datastore.driver | string | `"etcd"` | (string) The Kamaji Datastore driver, supported: etcd, MySQL, PostgreSQL (defaults=etcd). |
|
||||
| datastore.enabled | bool | `true` | (bool) Enable the Kamaji Datastore creation (default=true) |
|
||||
| datastore.endpoints | list | `[]` | (array) List of endpoints of the selected Datastore. When letting the Chart install the etcd datastore, this field is populated automatically. |
|
||||
| datastore.nameOverride | string | `nil` | The Datastore name override, if empty defaults to `default` |
|
||||
| datastore.nameOverride | string | `nil` | The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to. |
|
||||
| datastore.tlsConfig.certificateAuthority.certificate.keyPath | string | `nil` | Key of the Secret which contains the content of the certificate. |
|
||||
| datastore.tlsConfig.certificateAuthority.certificate.name | string | `nil` | Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. |
|
||||
| datastore.tlsConfig.certificateAuthority.certificate.namespace | string | `nil` | Namespace of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. |
|
||||
@@ -100,10 +103,11 @@ Here the values you can override:
|
||||
| etcd.persistence.accessModes[0] | string | `"ReadWriteOnce"` | |
|
||||
| etcd.persistence.customAnnotations | object | `{}` | The custom annotations to add to the PVC |
|
||||
| etcd.persistence.size | string | `"10Gi"` | |
|
||||
| etcd.persistence.storageClass | string | `""` | |
|
||||
| etcd.persistence.storageClassName | string | `""` | |
|
||||
| etcd.port | int | `2379` | The client request port. |
|
||||
| etcd.serviceAccount.create | bool | `true` | Create a ServiceAccount, required to install and provision the etcd backing storage (default: true) |
|
||||
| etcd.serviceAccount.name | string | `""` | Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "") |
|
||||
| etcd.tolerations | list | `[]` | (array) Kubernetes affinity rules to apply to Kamaji etcd pods |
|
||||
| extraArgs | list | `[]` | A list of extra arguments to add to the kamaji controller default ones |
|
||||
| fullnameOverride | string | `""` | |
|
||||
| healthProbeBindAddress | string | `":8081"` | The address the probe endpoint binds to. (default ":8081") |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,11 @@
|
||||
Create a default fully qualified datastore name.
|
||||
*/}}
|
||||
{{- define "datastore.fullname" -}}
|
||||
{{- if .Values.datastore.enabled }}
|
||||
{{- default "default" .Values.datastore.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- required "A valid .Values.datastore.nameOverride required!" .Values.datastore.nameOverride }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{{- if .Values.datastore.enabled}}
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: DataStore
|
||||
metadata:
|
||||
@@ -24,3 +25,4 @@ spec:
|
||||
{{- include "datastore.certificateAuthority" . | indent 6 }}
|
||||
clientCertificate:
|
||||
{{- include "datastore.clientCertificate" . | indent 6 }}
|
||||
{{- end}}
|
||||
|
||||
@@ -30,11 +30,15 @@ spec:
|
||||
- bash
|
||||
- -c
|
||||
- |-
|
||||
etcdctl member list -w table &&
|
||||
etcdctl user add --no-password=true root &&
|
||||
etcdctl role add root &&
|
||||
etcdctl user grant-role root root &&
|
||||
etcdctl auth enable
|
||||
etcdctl member list -w table
|
||||
if etcdctl user get root &>/dev/null; then
|
||||
echo "User already exists, nothing to do"
|
||||
else
|
||||
etcdctl user add --no-password=true root &&
|
||||
etcdctl role add root &&
|
||||
etcdctl user grant-role root root &&
|
||||
etcdctl auth enable
|
||||
fi
|
||||
env:
|
||||
- name: ETCDCTL_ENDPOINTS
|
||||
value: https://etcd-0.{{ include "etcd.serviceName" . }}.{{ .Release.Namespace }}.svc.cluster.local:2379
|
||||
|
||||
@@ -19,7 +19,7 @@ spec:
|
||||
restartPolicy: Never
|
||||
initContainers:
|
||||
- name: cfssl
|
||||
image: cfssl/cfssl:latest
|
||||
image: "{{ .Values.cfssl.image.repository }}:{{ .Values.cfssl.image.tag }}"
|
||||
command:
|
||||
- bash
|
||||
- -c
|
||||
@@ -37,13 +37,21 @@ spec:
|
||||
containers:
|
||||
- name: kubectl
|
||||
image: {{ printf "clastix/kubectl:%s" (include "etcd.jobsTagKubeVersion" .) }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |-
|
||||
kubectl --namespace={{ .Release.Namespace }} delete secret --ignore-not-found=true {{ include "etcd.caSecretName" . }} {{ include "etcd.clientSecretName" . }} &&
|
||||
kubectl --namespace={{ .Release.Namespace }} create secret generic {{ include "etcd.caSecretName" . }} --from-file=/certs/ca.crt --from-file=/certs/ca.key --from-file=/certs/peer-key.pem --from-file=/certs/peer.pem --from-file=/certs/server-key.pem --from-file=/certs/server.pem &&
|
||||
kubectl --namespace={{ .Release.Namespace }} create secret tls {{ include "etcd.clientSecretName" . }} --key=/certs/root-client-key.pem --cert=/certs/root-client.pem
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
if kubectl get secret {{ include "etcd.caSecretName" . }} --namespace={{ .Release.Namespace }} &>/dev/null; then
|
||||
echo "Secret {{ include "etcd.caSecretName" . }} already exists"
|
||||
else
|
||||
echo "Creating secret {{ include "etcd.caSecretName" . }}"
|
||||
kubectl --namespace={{ .Release.Namespace }} create secret generic {{ include "etcd.caSecretName" . }} --from-file=/certs/ca.crt --from-file=/certs/ca.key --from-file=/certs/peer-key.pem --from-file=/certs/peer.pem --from-file=/certs/server-key.pem --from-file=/certs/server.pem
|
||||
fi
|
||||
if kubectl get secret {{ include "etcd.clientSecretName" . }} --namespace={{ .Release.Namespace }} &>/dev/null; then
|
||||
echo "Secret {{ include "etcd.clientSecretName" . }} already exists"
|
||||
else
|
||||
echo "Creating secret {{ include "etcd.clientSecretName" . }}"
|
||||
kubectl --namespace={{ .Release.Namespace }} create secret tls {{ include "etcd.clientSecretName" . }} --key=/certs/root-client-key.pem --cert=/certs/root-client.pem
|
||||
fi
|
||||
volumeMounts:
|
||||
- mountPath: /certs
|
||||
name: certs
|
||||
|
||||
@@ -15,6 +15,7 @@ rules:
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- delete
|
||||
resourceNames:
|
||||
- {{ include "etcd.caSecretName" . }}
|
||||
|
||||
@@ -22,6 +22,10 @@ spec:
|
||||
- name: certs
|
||||
secret:
|
||||
secretName: {{ include "etcd.caSecretName" . }}
|
||||
{{- with .Values.etcd.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: etcd
|
||||
image: {{ .Values.etcd.image.repository }}:{{ .Values.etcd.image.tag | default "v3.5.4" }}
|
||||
|
||||
@@ -54,12 +54,15 @@ etcd:
|
||||
name: ""
|
||||
persistence:
|
||||
size: 10Gi
|
||||
storageClass: ""
|
||||
storageClassName: ""
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
# -- The custom annotations to add to the PVC
|
||||
customAnnotations: {}
|
||||
# volumeType: local
|
||||
|
||||
# -- (array) Kubernetes affinity rules to apply to Kamaji etcd pods
|
||||
tolerations: []
|
||||
|
||||
overrides:
|
||||
caSecret:
|
||||
@@ -157,7 +160,9 @@ loggingDevel:
|
||||
enable: false
|
||||
|
||||
datastore:
|
||||
# -- (string) The Datastore name override, if empty defaults to `default`
|
||||
# -- (bool) Enable the Kamaji Datastore creation (default=true)
|
||||
enabled: true
|
||||
# -- (string) The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to.
|
||||
nameOverride:
|
||||
# -- (string) The Kamaji Datastore driver, supported: etcd, MySQL, PostgreSQL (defaults=etcd).
|
||||
driver: etcd
|
||||
@@ -209,3 +214,8 @@ datastore:
|
||||
namespace:
|
||||
# -- Key of the Secret which contains the content of the private key.
|
||||
keyPath:
|
||||
|
||||
cfssl:
|
||||
image:
|
||||
repository: cfssl/cfssl
|
||||
tag: latest
|
||||
@@ -20,6 +20,8 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||
ctrlwebhook "sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
cmdutils "github.com/clastix/kamaji/cmd/utils"
|
||||
@@ -95,15 +97,19 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command {
|
||||
setupLog.Info(fmt.Sprintf("Go OS/Arch: %s/%s", goRuntime.GOOS, goRuntime.GOARCH))
|
||||
|
||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||
Scheme: scheme,
|
||||
MetricsBindAddress: metricsBindAddress,
|
||||
Port: 9443,
|
||||
Scheme: scheme,
|
||||
Metrics: metricsserver.Options{
|
||||
BindAddress: metricsBindAddress,
|
||||
},
|
||||
WebhookServer: ctrlwebhook.NewServer(ctrlwebhook.Options{
|
||||
Port: 9443,
|
||||
}),
|
||||
HealthProbeBindAddress: healthProbeBindAddress,
|
||||
LeaderElection: leaderElect,
|
||||
LeaderElectionNamespace: managerNamespace,
|
||||
LeaderElectionID: "799b98bc.clastix.io",
|
||||
NewCache: func(config *rest.Config, opts cache.Options) (cache.Cache, error) {
|
||||
opts.Resync = &cacheResyncPeriod
|
||||
opts.SyncPeriod = &cacheResyncPeriod
|
||||
|
||||
return cache.New(config, opts)
|
||||
},
|
||||
@@ -116,7 +122,7 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command {
|
||||
|
||||
tcpChannel, certChannel := make(controllers.TenantControlPlaneChannel), make(controllers.CertificateChannel)
|
||||
|
||||
if err = (&controllers.DataStore{TenantControlPlaneTrigger: tcpChannel}).SetupWithManager(mgr); err != nil {
|
||||
if err = (&controllers.DataStore{Client: mgr.GetClient(), TenantControlPlaneTrigger: tcpChannel}).SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to create controller", "controller", "DataStore")
|
||||
|
||||
return err
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
_ "go.uber.org/automaxprocs" // Automatically set `GOMAXPROCS` to match Linux container CPU quota.
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -22,9 +19,6 @@ func NewCmd(scheme *runtime.Scheme) *cobra.Command {
|
||||
Use: "kamaji",
|
||||
Short: "Build and operate Kubernetes at scale with a fraction of operational burden.",
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
// Seed is required to ensure non reproducibility for the certificates generate by Kamaji.
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||
utilruntime.Must(kamajiv1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(appsv1.RegisterDefaults(scheme))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -340,7 +340,7 @@ spec:
|
||||
version: v0.0.32
|
||||
properties:
|
||||
extraArgs:
|
||||
description: ExtraArgs allows adding additional arguments to said component.
|
||||
description: ExtraArgs allows adding additional arguments to said component. WARNING - This option can override existing konnectivity parameters and cause konnectivity components to misbehave in unxpected ways. Only modify if you know what you are doing.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
@@ -360,7 +360,7 @@ spec:
|
||||
version: v0.0.32
|
||||
properties:
|
||||
extraArgs:
|
||||
description: ExtraArgs allows adding additional arguments to said component.
|
||||
description: ExtraArgs allows adding additional arguments to said component. WARNING - This option can override existing konnectivity parameters and cause konnectivity components to misbehave in unxpected ways. Only modify if you know what you are doing.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
@@ -376,7 +376,7 @@ spec:
|
||||
description: Resources define the amount of CPU and memory to allocate to the Konnectivity server.
|
||||
properties:
|
||||
claims:
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable."
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers."
|
||||
items:
|
||||
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
|
||||
properties:
|
||||
@@ -406,7 +406,7 @@ spec:
|
||||
- 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: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
version:
|
||||
@@ -598,7 +598,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -623,6 +623,16 @@ spec:
|
||||
required:
|
||||
- port
|
||||
type: object
|
||||
sleep:
|
||||
description: Sleep represents the duration that the container should sleep before being terminated.
|
||||
properties:
|
||||
seconds:
|
||||
description: Seconds is the number of seconds to sleep.
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- seconds
|
||||
type: object
|
||||
tcpSocket:
|
||||
description: Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept for the backward compatibility. There are no validation of this field and lifecycle hooks will fail in runtime when tcp handler is specified.
|
||||
properties:
|
||||
@@ -663,7 +673,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -688,6 +698,16 @@ spec:
|
||||
required:
|
||||
- port
|
||||
type: object
|
||||
sleep:
|
||||
description: Sleep represents the duration that the container should sleep before being terminated.
|
||||
properties:
|
||||
seconds:
|
||||
description: Seconds is the number of seconds to sleep.
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- seconds
|
||||
type: object
|
||||
tcpSocket:
|
||||
description: Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept for the backward compatibility. There are no validation of this field and lifecycle hooks will fail in runtime when tcp handler is specified.
|
||||
properties:
|
||||
@@ -722,7 +742,7 @@ spec:
|
||||
format: int32
|
||||
type: integer
|
||||
grpc:
|
||||
description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate.
|
||||
description: GRPC specifies an action involving a GRPC port.
|
||||
properties:
|
||||
port:
|
||||
description: Port number of the gRPC service. Number must be in the range 1 to 65535.
|
||||
@@ -746,7 +766,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -858,7 +878,7 @@ spec:
|
||||
format: int32
|
||||
type: integer
|
||||
grpc:
|
||||
description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate.
|
||||
description: GRPC specifies an action involving a GRPC port.
|
||||
properties:
|
||||
port:
|
||||
description: Port number of the gRPC service. Number must be in the range 1 to 65535.
|
||||
@@ -882,7 +902,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -943,11 +963,28 @@ spec:
|
||||
format: int32
|
||||
type: integer
|
||||
type: object
|
||||
resizePolicy:
|
||||
description: Resources resize policy for the container.
|
||||
items:
|
||||
description: ContainerResizePolicy represents resource resize policy for the container.
|
||||
properties:
|
||||
resourceName:
|
||||
description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.'
|
||||
type: string
|
||||
restartPolicy:
|
||||
description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired.
|
||||
type: string
|
||||
required:
|
||||
- resourceName
|
||||
- restartPolicy
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
resources:
|
||||
description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
properties:
|
||||
claims:
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable."
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers."
|
||||
items:
|
||||
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
|
||||
properties:
|
||||
@@ -977,9 +1014,12 @@ spec:
|
||||
- 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: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: 'RestartPolicy defines the restart behavior of individual containers in a pod. This field may only be set for init containers, and the only allowed value is "Always". For non-init containers or when this field is not specified, the restart behavior is defined by the Pod''s restart policy and the container type. Setting the RestartPolicy as "Always" for the init container will have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" will be shut down. This lifecycle differs from normal init containers and is often referred to as a "sidecar" container. Although this init container still starts in the init container sequence, it does not wait for the container to complete before proceeding to the next init container. Instead, the next init container starts immediately after this init container is started, or after any startupProbe has successfully completed.'
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'SecurityContext defines the security options the container should be run with. If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/'
|
||||
properties:
|
||||
@@ -1042,7 +1082,7 @@ spec:
|
||||
description: The seccomp options to use by this container. If seccomp options are provided at both the pod & container level, the container options override the pod options. Note that this field cannot be set when spec.os.name is windows.
|
||||
properties:
|
||||
localhostProfile:
|
||||
description: localhostProfile indicates a profile defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. Must only be set if type is "Localhost".
|
||||
description: localhostProfile indicates a profile defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. Must be set if type is "Localhost". Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind of seccomp profile will be applied. Valid options are: \n Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied."
|
||||
@@ -1060,7 +1100,7 @@ spec:
|
||||
description: GMSACredentialSpecName is the name of the GMSA credential spec to use.
|
||||
type: string
|
||||
hostProcess:
|
||||
description: HostProcess determines if a container should be run as a 'Host Process' container. This field is alpha-level and will only be honored by components that enable the WindowsHostProcessContainers feature flag. Setting this field without the feature flag will result in errors when validating the Pod. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true.
|
||||
description: HostProcess determines if a container should be run as a 'Host Process' container. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||
@@ -1084,7 +1124,7 @@ spec:
|
||||
format: int32
|
||||
type: integer
|
||||
grpc:
|
||||
description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate.
|
||||
description: GRPC specifies an action involving a GRPC port.
|
||||
properties:
|
||||
port:
|
||||
description: Port number of the gRPC service. Number must be in the range 1 to 65535.
|
||||
@@ -1108,7 +1148,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -1399,7 +1439,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -1424,6 +1464,16 @@ spec:
|
||||
required:
|
||||
- port
|
||||
type: object
|
||||
sleep:
|
||||
description: Sleep represents the duration that the container should sleep before being terminated.
|
||||
properties:
|
||||
seconds:
|
||||
description: Seconds is the number of seconds to sleep.
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- seconds
|
||||
type: object
|
||||
tcpSocket:
|
||||
description: Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept for the backward compatibility. There are no validation of this field and lifecycle hooks will fail in runtime when tcp handler is specified.
|
||||
properties:
|
||||
@@ -1464,7 +1514,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -1489,6 +1539,16 @@ spec:
|
||||
required:
|
||||
- port
|
||||
type: object
|
||||
sleep:
|
||||
description: Sleep represents the duration that the container should sleep before being terminated.
|
||||
properties:
|
||||
seconds:
|
||||
description: Seconds is the number of seconds to sleep.
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- seconds
|
||||
type: object
|
||||
tcpSocket:
|
||||
description: Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept for the backward compatibility. There are no validation of this field and lifecycle hooks will fail in runtime when tcp handler is specified.
|
||||
properties:
|
||||
@@ -1523,7 +1583,7 @@ spec:
|
||||
format: int32
|
||||
type: integer
|
||||
grpc:
|
||||
description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate.
|
||||
description: GRPC specifies an action involving a GRPC port.
|
||||
properties:
|
||||
port:
|
||||
description: Port number of the gRPC service. Number must be in the range 1 to 65535.
|
||||
@@ -1547,7 +1607,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -1659,7 +1719,7 @@ spec:
|
||||
format: int32
|
||||
type: integer
|
||||
grpc:
|
||||
description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate.
|
||||
description: GRPC specifies an action involving a GRPC port.
|
||||
properties:
|
||||
port:
|
||||
description: Port number of the gRPC service. Number must be in the range 1 to 65535.
|
||||
@@ -1683,7 +1743,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -1744,11 +1804,28 @@ spec:
|
||||
format: int32
|
||||
type: integer
|
||||
type: object
|
||||
resizePolicy:
|
||||
description: Resources resize policy for the container.
|
||||
items:
|
||||
description: ContainerResizePolicy represents resource resize policy for the container.
|
||||
properties:
|
||||
resourceName:
|
||||
description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.'
|
||||
type: string
|
||||
restartPolicy:
|
||||
description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired.
|
||||
type: string
|
||||
required:
|
||||
- resourceName
|
||||
- restartPolicy
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
resources:
|
||||
description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
properties:
|
||||
claims:
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable."
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers."
|
||||
items:
|
||||
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
|
||||
properties:
|
||||
@@ -1778,9 +1855,12 @@ spec:
|
||||
- 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: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: 'RestartPolicy defines the restart behavior of individual containers in a pod. This field may only be set for init containers, and the only allowed value is "Always". For non-init containers or when this field is not specified, the restart behavior is defined by the Pod''s restart policy and the container type. Setting the RestartPolicy as "Always" for the init container will have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" will be shut down. This lifecycle differs from normal init containers and is often referred to as a "sidecar" container. Although this init container still starts in the init container sequence, it does not wait for the container to complete before proceeding to the next init container. Instead, the next init container starts immediately after this init container is started, or after any startupProbe has successfully completed.'
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'SecurityContext defines the security options the container should be run with. If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/'
|
||||
properties:
|
||||
@@ -1843,7 +1923,7 @@ spec:
|
||||
description: The seccomp options to use by this container. If seccomp options are provided at both the pod & container level, the container options override the pod options. Note that this field cannot be set when spec.os.name is windows.
|
||||
properties:
|
||||
localhostProfile:
|
||||
description: localhostProfile indicates a profile defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. Must only be set if type is "Localhost".
|
||||
description: localhostProfile indicates a profile defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. Must be set if type is "Localhost". Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind of seccomp profile will be applied. Valid options are: \n Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied."
|
||||
@@ -1861,7 +1941,7 @@ spec:
|
||||
description: GMSACredentialSpecName is the name of the GMSA credential spec to use.
|
||||
type: string
|
||||
hostProcess:
|
||||
description: HostProcess determines if a container should be run as a 'Host Process' container. This field is alpha-level and will only be honored by components that enable the WindowsHostProcessContainers feature flag. Setting this field without the feature flag will result in errors when validating the Pod. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true.
|
||||
description: HostProcess determines if a container should be run as a 'Host Process' container. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||
@@ -1885,7 +1965,7 @@ spec:
|
||||
format: int32
|
||||
type: integer
|
||||
grpc:
|
||||
description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate.
|
||||
description: GRPC specifies an action involving a GRPC port.
|
||||
properties:
|
||||
port:
|
||||
description: Port number of the gRPC service. Number must be in the range 1 to 65535.
|
||||
@@ -1909,7 +1989,7 @@ spec:
|
||||
description: HTTPHeader describes a custom header to be used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
@@ -2382,7 +2462,7 @@ spec:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir'
|
||||
description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir'
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
type: object
|
||||
@@ -2442,21 +2522,6 @@ spec:
|
||||
resources:
|
||||
description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
|
||||
properties:
|
||||
claims:
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable."
|
||||
items:
|
||||
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
|
||||
properties:
|
||||
name:
|
||||
description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- name
|
||||
x-kubernetes-list-type: map
|
||||
limits:
|
||||
additionalProperties:
|
||||
anyOf:
|
||||
@@ -2473,7 +2538,7 @@ spec:
|
||||
- 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: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
selector:
|
||||
@@ -2510,6 +2575,9 @@ spec:
|
||||
storageClassName:
|
||||
description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
|
||||
type: string
|
||||
volumeAttributesClassName:
|
||||
description: 'volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass will be applied to the claim but it''s not allowed to reset this field to empty string once it is set. If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass will be set by the persistentvolume controller if it exists. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled.'
|
||||
type: string
|
||||
volumeMode:
|
||||
description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.
|
||||
type: string
|
||||
@@ -2764,6 +2832,55 @@ spec:
|
||||
items:
|
||||
description: Projection that may be projected along with other supported volume types
|
||||
properties:
|
||||
clusterTrustBundle:
|
||||
description: "ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. \n Alpha, gated by the ClusterTrustBundleProjection feature gate. \n ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. \n Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. The ordering of certificates within the file is arbitrary, and Kubelet may change the order over time."
|
||||
properties:
|
||||
labelSelector:
|
||||
description: Select all ClusterTrustBundles that match this label selector. Only has effect if signerName is set. Mutually-exclusive with name. If unset, interpreted as "match nothing". If set but empty, interpreted as "match everything".
|
||||
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
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
type: object
|
||||
type: array
|
||||
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
|
||||
name:
|
||||
description: Select a single ClusterTrustBundle by object name. Mutually-exclusive with signerName and labelSelector.
|
||||
type: string
|
||||
optional:
|
||||
description: If true, don't block pod startup if the referenced ClusterTrustBundle(s) aren't available. If using name, then the named ClusterTrustBundle is allowed not to exist. If using signerName, then the combination of signerName and labelSelector is allowed to match zero ClusterTrustBundles.
|
||||
type: boolean
|
||||
path:
|
||||
description: Relative path from the volume root to write the bundle.
|
||||
type: string
|
||||
signerName:
|
||||
description: Select all ClusterTrustBundles that match this signer name. Mutually-exclusive with name. The contents of all selected ClusterTrustBundles will be unified and deduplicated.
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
type: object
|
||||
configMap:
|
||||
description: configMap information about the configMap data to project
|
||||
properties:
|
||||
@@ -3221,7 +3338,7 @@ spec:
|
||||
description: Required. A pod affinity term, associated with the corresponding weight.
|
||||
properties:
|
||||
labelSelector:
|
||||
description: A label query over a set of resources, in this case pods.
|
||||
description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
|
||||
@@ -3251,6 +3368,18 @@ spec:
|
||||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
matchLabelKeys:
|
||||
description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
mismatchLabelKeys:
|
||||
description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
namespaceSelector:
|
||||
description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces.
|
||||
properties:
|
||||
@@ -3308,7 +3437,7 @@ spec:
|
||||
description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key <topologyKey> matches that of any node on which a pod of the set of pods is running
|
||||
properties:
|
||||
labelSelector:
|
||||
description: A label query over a set of resources, in this case pods.
|
||||
description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
|
||||
@@ -3338,6 +3467,18 @@ spec:
|
||||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
matchLabelKeys:
|
||||
description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
mismatchLabelKeys:
|
||||
description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
namespaceSelector:
|
||||
description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces.
|
||||
properties:
|
||||
@@ -3394,7 +3535,7 @@ spec:
|
||||
description: Required. A pod affinity term, associated with the corresponding weight.
|
||||
properties:
|
||||
labelSelector:
|
||||
description: A label query over a set of resources, in this case pods.
|
||||
description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
|
||||
@@ -3424,6 +3565,18 @@ spec:
|
||||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
matchLabelKeys:
|
||||
description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
mismatchLabelKeys:
|
||||
description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
namespaceSelector:
|
||||
description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces.
|
||||
properties:
|
||||
@@ -3481,7 +3634,7 @@ spec:
|
||||
description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key <topologyKey> matches that of any node on which a pod of the set of pods is running
|
||||
properties:
|
||||
labelSelector:
|
||||
description: A label query over a set of resources, in this case pods.
|
||||
description: A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
|
||||
@@ -3511,6 +3664,18 @@ spec:
|
||||
type: object
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
matchLabelKeys:
|
||||
description: MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. Also, MatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
mismatchLabelKeys:
|
||||
description: MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
namespaceSelector:
|
||||
description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces.
|
||||
properties:
|
||||
@@ -3557,7 +3722,7 @@ spec:
|
||||
type: object
|
||||
type: object
|
||||
extraArgs:
|
||||
description: ExtraArgs allows adding additional arguments to the Control Plane components, such as kube-apiserver, controller-manager, and scheduler.
|
||||
description: ExtraArgs allows adding additional arguments to the Control Plane components, such as kube-apiserver, controller-manager, and scheduler. WARNING - This option can override existing parameters and cause components to misbehave in unxpected ways. Only modify if you know what you are doing.
|
||||
properties:
|
||||
apiServer:
|
||||
items:
|
||||
@@ -3617,7 +3782,7 @@ spec:
|
||||
description: ResourceRequirements describes the compute resource requirements.
|
||||
properties:
|
||||
claims:
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable."
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers."
|
||||
items:
|
||||
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
|
||||
properties:
|
||||
@@ -3647,14 +3812,14 @@ spec:
|
||||
- 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: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
controllerManager:
|
||||
description: ResourceRequirements describes the compute resource requirements.
|
||||
properties:
|
||||
claims:
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable."
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers."
|
||||
items:
|
||||
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
|
||||
properties:
|
||||
@@ -3684,14 +3849,14 @@ spec:
|
||||
- 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: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
kine:
|
||||
description: Define the kine container resources. Available only if Kamaji is running using Kine as backing storage.
|
||||
properties:
|
||||
claims:
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable."
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers."
|
||||
items:
|
||||
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
|
||||
properties:
|
||||
@@ -3721,14 +3886,14 @@ spec:
|
||||
- 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: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
scheduler:
|
||||
description: ResourceRequirements describes the compute resource requirements.
|
||||
properties:
|
||||
claims:
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable."
|
||||
description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers."
|
||||
items:
|
||||
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
|
||||
properties:
|
||||
@@ -3758,7 +3923,7 @@ spec:
|
||||
- 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: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
@@ -3853,7 +4018,7 @@ spec:
|
||||
type: object
|
||||
x-kubernetes-map-type: atomic
|
||||
matchLabelKeys:
|
||||
description: MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector.
|
||||
description: "MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. \n This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default)."
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
@@ -4219,6 +4384,9 @@ spec:
|
||||
ip:
|
||||
description: IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers)
|
||||
type: string
|
||||
ipMode:
|
||||
description: IPMode specifies how the load-balancer IP behaves, and may only be specified when the ip field is specified. Setting this to "VIP" indicates that traffic is delivered to the node with the destination set to the load-balancer's IP and port. Setting this to "Proxy" indicates that traffic is delivered to the node or pod with the destination set to the node's IP and node port or the pod's IP and port. Service implementations may use this information to adjust traffic routing.
|
||||
type: string
|
||||
ports:
|
||||
description: Ports is a list of records of service ports If used, every port defined in the service should have an entry in it
|
||||
items:
|
||||
@@ -4524,36 +4692,36 @@ spec:
|
||||
description: KubernetesIngressStatus defines the status for the Tenant Control Plane Ingress in the management cluster.
|
||||
properties:
|
||||
loadBalancer:
|
||||
description: LoadBalancer contains the current status of the load-balancer.
|
||||
description: loadBalancer contains the current status of the load-balancer.
|
||||
properties:
|
||||
ingress:
|
||||
description: Ingress is a list containing ingress points for the load-balancer.
|
||||
description: ingress is a list containing ingress points for the load-balancer.
|
||||
items:
|
||||
description: IngressLoadBalancerIngress represents the status of a load-balancer ingress point.
|
||||
properties:
|
||||
hostname:
|
||||
description: Hostname is set for load-balancer ingress points that are DNS based.
|
||||
description: hostname is set for load-balancer ingress points that are DNS based.
|
||||
type: string
|
||||
ip:
|
||||
description: IP is set for load-balancer ingress points that are IP based.
|
||||
description: ip is set for load-balancer ingress points that are IP based.
|
||||
type: string
|
||||
ports:
|
||||
description: Ports provides information about the ports exposed by this LoadBalancer.
|
||||
description: ports provides information about the ports exposed by this LoadBalancer.
|
||||
items:
|
||||
description: IngressPortStatus represents the error condition of a service port
|
||||
properties:
|
||||
error:
|
||||
description: 'Error is to record the problem with the service port The format of the error shall comply with the following rules: - built-in error values shall be specified in this file and those shall use CamelCase names - cloud provider specific error values must have names that comply with the format foo.example.com/CamelCase. --- The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)'
|
||||
description: 'error is to record the problem with the service port The format of the error shall comply with the following rules: - built-in error values shall be specified in this file and those shall use CamelCase names - cloud provider specific error values must have names that comply with the format foo.example.com/CamelCase. --- The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)'
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
port:
|
||||
description: Port is the port number of the ingress port.
|
||||
description: port is the port number of the ingress port.
|
||||
format: int32
|
||||
type: integer
|
||||
protocol:
|
||||
default: TCP
|
||||
description: 'Protocol is the protocol of the ingress port. The supported values are: "TCP", "UDP", "SCTP"'
|
||||
description: 'protocol is the protocol of the ingress port. The supported values are: "TCP", "UDP", "SCTP"'
|
||||
type: string
|
||||
required:
|
||||
- port
|
||||
@@ -4638,6 +4806,9 @@ spec:
|
||||
ip:
|
||||
description: IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers)
|
||||
type: string
|
||||
ipMode:
|
||||
description: IPMode specifies how the load-balancer IP behaves, and may only be specified when the ip field is specified. Setting this to "VIP" indicates that traffic is delivered to the node with the destination set to the load-balancer's IP and port. Setting this to "Proxy" indicates that traffic is delivered to the node or pod with the destination set to the node's IP and node port or the pod's IP and port. Service implementations may use this information to adjust traffic routing.
|
||||
type: string
|
||||
ports:
|
||||
description: Ports is a list of records of service ports If used, every port defined in the service should have an entry in it
|
||||
items:
|
||||
@@ -5093,7 +5264,7 @@ spec:
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.serviceAccountName
|
||||
image: clastix/kamaji:v0.3.4
|
||||
image: clastix/kamaji:v0.4.2
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -13,4 +13,4 @@ kind: Kustomization
|
||||
images:
|
||||
- name: controller
|
||||
newName: clastix/kamaji
|
||||
newTag: v0.3.4
|
||||
newTag: v0.4.2
|
||||
|
||||
@@ -40,12 +40,16 @@ func (s *CertificateLifecycle) Reconcile(ctx context.Context, request reconcile.
|
||||
logger.Info("starting CertificateLifecycle handling")
|
||||
|
||||
secret := corev1.Secret{}
|
||||
if err := s.client.Get(ctx, request.NamespacedName, &secret); err != nil {
|
||||
if k8serrors.IsNotFound(err) {
|
||||
logger.Info("resource may have been deleted, skipping")
|
||||
err := s.client.Get(ctx, request.NamespacedName, &secret)
|
||||
if k8serrors.IsNotFound(err) {
|
||||
logger.Info("resource have been deleted, skipping")
|
||||
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
if err != nil {
|
||||
logger.Error(err, "cannot retrieve the required resource")
|
||||
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
checkType, ok := secret.GetLabels()[constants.ControllerLabelResource]
|
||||
@@ -56,7 +60,6 @@ func (s *CertificateLifecycle) Reconcile(ctx context.Context, request reconcile.
|
||||
}
|
||||
|
||||
var crt *x509.Certificate
|
||||
var err error
|
||||
|
||||
switch checkType {
|
||||
case "x509":
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
type DataStore struct {
|
||||
client client.Client
|
||||
Client client.Client
|
||||
// TenantControlPlaneTrigger is the channel used to communicate across the controllers:
|
||||
// if a Data Source is updated we have to be sure that the reconciliation of the certificates content
|
||||
// for each Tenant Control Plane is put in place properly.
|
||||
@@ -39,19 +39,21 @@ func (r *DataStore) Reconcile(ctx context.Context, request reconcile.Request) (r
|
||||
log := log.FromContext(ctx)
|
||||
|
||||
ds := &kamajiv1alpha1.DataStore{}
|
||||
if err := r.client.Get(ctx, request.NamespacedName, ds); err != nil {
|
||||
if k8serrors.IsNotFound(err) {
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
err := r.Client.Get(ctx, request.NamespacedName, ds)
|
||||
if k8serrors.IsNotFound(err) {
|
||||
log.Info("resource have been deleted, skipping")
|
||||
|
||||
log.Error(err, "unable to retrieve the request")
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
if err != nil {
|
||||
log.Error(err, "cannot retrieve the required resource")
|
||||
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
tcpList := kamajiv1alpha1.TenantControlPlaneList{}
|
||||
|
||||
if err := r.client.List(ctx, &tcpList, client.MatchingFieldsSelector{
|
||||
if err := r.Client.List(ctx, &tcpList, client.MatchingFieldsSelector{
|
||||
Selector: fields.OneTermEqualSelector(kamajiv1alpha1.TenantControlPlaneUsedDataStoreKey, ds.GetName()),
|
||||
}); err != nil {
|
||||
log.Error(err, "cannot retrieve list of the Tenant Control Plane using the following instance")
|
||||
@@ -66,7 +68,7 @@ func (r *DataStore) Reconcile(ctx context.Context, request reconcile.Request) (r
|
||||
|
||||
ds.Status.UsedBy = tcpSets.List()
|
||||
|
||||
if err := r.client.Status().Update(ctx, ds); err != nil {
|
||||
if err := r.Client.Status().Update(ctx, ds); err != nil {
|
||||
log.Error(err, "cannot update the status for the given instance")
|
||||
|
||||
return reconcile.Result{}, err
|
||||
@@ -81,12 +83,6 @@ func (r *DataStore) Reconcile(ctx context.Context, request reconcile.Request) (r
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
func (r *DataStore) InjectClient(client client.Client) error {
|
||||
r.client = client
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DataStore) SetupWithManager(mgr controllerruntime.Manager) error {
|
||||
enqueueFn := func(tcp *kamajiv1alpha1.TenantControlPlane, limitingInterface workqueue.RateLimitingInterface) {
|
||||
if dataStoreName := tcp.Status.Storage.DataStoreName; len(dataStoreName) > 0 {
|
||||
@@ -102,15 +98,15 @@ func (r *DataStore) SetupWithManager(mgr controllerruntime.Manager) error {
|
||||
For(&kamajiv1alpha1.DataStore{}, builder.WithPredicates(
|
||||
predicate.ResourceVersionChangedPredicate{},
|
||||
)).
|
||||
Watches(&source.Kind{Type: &kamajiv1alpha1.TenantControlPlane{}}, handler.Funcs{
|
||||
CreateFunc: func(createEvent event.CreateEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
WatchesRawSource(source.Kind(mgr.GetCache(), &kamajiv1alpha1.TenantControlPlane{}), handler.Funcs{
|
||||
CreateFunc: func(_ context.Context, createEvent event.CreateEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
enqueueFn(createEvent.Object.(*kamajiv1alpha1.TenantControlPlane), limitingInterface)
|
||||
},
|
||||
UpdateFunc: func(updateEvent event.UpdateEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
UpdateFunc: func(_ context.Context, updateEvent event.UpdateEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
enqueueFn(updateEvent.ObjectOld.(*kamajiv1alpha1.TenantControlPlane), limitingInterface)
|
||||
enqueueFn(updateEvent.ObjectNew.(*kamajiv1alpha1.TenantControlPlane), limitingInterface)
|
||||
},
|
||||
DeleteFunc: func(deleteEvent event.DeleteEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
DeleteFunc: func(_ context.Context, deleteEvent event.DeleteEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
enqueueFn(deleteEvent.Object.(*kamajiv1alpha1.TenantControlPlane), limitingInterface)
|
||||
},
|
||||
}).
|
||||
|
||||
@@ -5,6 +5,7 @@ package finalizers
|
||||
|
||||
const (
|
||||
// DatastoreFinalizer is using a wrong name, since it's related to the underlying datastore.
|
||||
DatastoreFinalizer = "finalizer.kamaji.clastix.io"
|
||||
SootFinalizer = "finalizer.kamaji.clastix.io/soot"
|
||||
DatastoreFinalizer = "finalizer.kamaji.clastix.io"
|
||||
DatastoreSecretFinalizer = "finalizer.kamaji.clastix.io/datastore-secret"
|
||||
SootFinalizer = "finalizer.kamaji.clastix.io/soot"
|
||||
)
|
||||
|
||||
@@ -40,6 +40,7 @@ type GroupDeletableResourceBuilderConfiguration struct {
|
||||
tcpReconcilerConfig TenantControlPlaneReconcilerConfig
|
||||
tenantControlPlane kamajiv1alpha1.TenantControlPlane
|
||||
connection datastore.Connection
|
||||
dataStore kamajiv1alpha1.DataStore
|
||||
}
|
||||
|
||||
// GetResources returns a list of resources that will be used to provide tenant control planes
|
||||
@@ -60,6 +61,11 @@ func GetDeletableResources(tcp *kamajiv1alpha1.TenantControlPlane, config GroupD
|
||||
Client: config.client,
|
||||
Connection: config.connection,
|
||||
})
|
||||
res = append(res, &ds.Config{
|
||||
Client: config.client,
|
||||
ConnString: config.connection.GetConnectionString(),
|
||||
DataStore: config.dataStore,
|
||||
})
|
||||
}
|
||||
|
||||
return res
|
||||
@@ -176,6 +182,12 @@ func getKubeconfigResources(c client.Client, tcpReconcilerConfig TenantControlPl
|
||||
KubeConfigFileName: resources.AdminKubeConfigFileName,
|
||||
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
|
||||
},
|
||||
&resources.KubeconfigResource{
|
||||
Name: "admin-kubeconfig",
|
||||
Client: c,
|
||||
KubeConfigFileName: resources.SuperAdminKubeConfigFileName,
|
||||
TmpDirectory: getTmpDirectory(tcpReconcilerConfig.TmpBaseDirectory, tenantControlPlane),
|
||||
},
|
||||
&resources.KubeconfigResource{
|
||||
Name: "controller-manager-kubeconfig",
|
||||
Client: c,
|
||||
|
||||
@@ -35,7 +35,7 @@ type CoreDNS struct {
|
||||
TriggerChannel chan event.GenericEvent
|
||||
}
|
||||
|
||||
func (c *CoreDNS) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
|
||||
func (c *CoreDNS) Reconcile(ctx context.Context, _ reconcile.Request) (reconcile.Result, error) {
|
||||
tcp, err := c.GetTenantControlPlaneFunc()
|
||||
if err != nil {
|
||||
c.logger.Error(err, "cannot retrieve TenantControlPlane")
|
||||
@@ -79,7 +79,7 @@ func (c *CoreDNS) SetupWithManager(mgr manager.Manager) error {
|
||||
For(&rbacv1.ClusterRoleBinding{}, builder.WithPredicates(predicate.NewPredicateFuncs(func(object client.Object) bool {
|
||||
return object.GetName() == kubeadm.CoreDNSClusterRoleBindingName
|
||||
}))).
|
||||
Watches(&source.Channel{Source: c.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
WatchesRawSource(&source.Channel{Source: c.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
Owns(&rbacv1.ClusterRole{}).
|
||||
Owns(&corev1.ServiceAccount{}).
|
||||
Owns(&corev1.Service{}).
|
||||
|
||||
@@ -80,7 +80,7 @@ func (k *KonnectivityAgent) SetupWithManager(mgr manager.Manager) error {
|
||||
For(&appsv1.DaemonSet{}, builder.WithPredicates(predicate.NewPredicateFuncs(func(object client.Object) bool {
|
||||
return object.GetName() == konnectivity.AgentName && object.GetNamespace() == konnectivity.AgentNamespace
|
||||
}))).
|
||||
Watches(&source.Kind{Type: &corev1.ServiceAccount{}}, handler.EnqueueRequestsFromMapFunc(func(object client.Object) []reconcile.Request {
|
||||
WatchesRawSource(source.Kind(mgr.GetCache(), &corev1.ServiceAccount{}), handler.EnqueueRequestsFromMapFunc(func(_ context.Context, object client.Object) []reconcile.Request {
|
||||
if object.GetName() == konnectivity.AgentName && object.GetNamespace() == konnectivity.AgentNamespace {
|
||||
return []reconcile.Request{
|
||||
{
|
||||
@@ -94,7 +94,7 @@ func (k *KonnectivityAgent) SetupWithManager(mgr manager.Manager) error {
|
||||
|
||||
return nil
|
||||
})).
|
||||
Watches(&source.Kind{Type: &v1.ClusterRoleBinding{}}, handler.EnqueueRequestsFromMapFunc(func(object client.Object) []reconcile.Request {
|
||||
WatchesRawSource(source.Kind(mgr.GetCache(), &v1.ClusterRoleBinding{}), handler.EnqueueRequestsFromMapFunc(func(_ context.Context, object client.Object) []reconcile.Request {
|
||||
if object.GetName() == konnectivity.CertCommonName {
|
||||
return []reconcile.Request{
|
||||
{
|
||||
@@ -107,6 +107,6 @@ func (k *KonnectivityAgent) SetupWithManager(mgr manager.Manager) error {
|
||||
|
||||
return nil
|
||||
})).
|
||||
Watches(&source.Channel{Source: k.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
WatchesRawSource(&source.Channel{Source: k.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
Complete(k)
|
||||
}
|
||||
|
||||
@@ -67,6 +67,6 @@ func (k *KubeadmPhase) SetupWithManager(mgr manager.Manager) error {
|
||||
|
||||
return controllerruntime.NewControllerManagedBy(mgr).
|
||||
For(k.Phase.GetWatchedObject(), builder.WithPredicates(predicate.NewPredicateFuncs(k.Phase.GetPredicateFunc()))).
|
||||
Watches(&source.Channel{Source: k.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
WatchesRawSource(&source.Channel{Source: k.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
Complete(k)
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func (k *KubeProxy) SetupWithManager(mgr manager.Manager) error {
|
||||
For(&rbacv1.ClusterRoleBinding{}, builder.WithPredicates(predicate.NewPredicateFuncs(func(object client.Object) bool {
|
||||
return object.GetName() == kubeadm.KubeProxyClusterRoleBindingName
|
||||
}))).
|
||||
Watches(&source.Channel{Source: k.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
WatchesRawSource(&source.Channel{Source: k.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
Owns(&corev1.ServiceAccount{}).
|
||||
Owns(&rbacv1.Role{}).
|
||||
Owns(&rbacv1.RoleBinding{}).
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/builder"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -84,7 +84,7 @@ func (m *Migrate) createOrUpdate(ctx context.Context) error {
|
||||
{
|
||||
Name: "leases.migrate.kamaji.clastix.io",
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
URL: pointer.String(fmt.Sprintf("https://%s.%s.svc:443/migrate", m.WebhookServiceName, m.WebhookNamespace)),
|
||||
URL: pointer.To(fmt.Sprintf("https://%s.%s.svc:443/migrate", m.WebhookServiceName, m.WebhookNamespace)),
|
||||
CABundle: m.WebhookCABundle,
|
||||
},
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
@@ -128,7 +128,7 @@ func (m *Migrate) createOrUpdate(ctx context.Context) error {
|
||||
{
|
||||
Name: "catchall.migrate.kamaji.clastix.io",
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
URL: pointer.String(fmt.Sprintf("https://%s.%s.svc:443/migrate", m.WebhookServiceName, m.WebhookNamespace)),
|
||||
URL: pointer.To(fmt.Sprintf("https://%s.%s.svc:443/migrate", m.WebhookServiceName, m.WebhookNamespace)),
|
||||
CABundle: m.WebhookCABundle,
|
||||
},
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
@@ -187,7 +187,7 @@ func (m *Migrate) SetupWithManager(mgr manager.Manager) error {
|
||||
|
||||
return object.GetName() == vwc.GetName()
|
||||
}))).
|
||||
Watches(&source.Channel{Source: m.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
WatchesRawSource(&source.Channel{Source: m.TriggerChannel}, &handler.EnqueueRequestForObject{}).
|
||||
Complete(m)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@ import (
|
||||
"k8s.io/client-go/util/retry"
|
||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/builder"
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
|
||||
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
@@ -175,10 +175,12 @@ func (m *Manager) Reconcile(ctx context.Context, request reconcile.Request) (res
|
||||
}()
|
||||
|
||||
mgr, err := controllerruntime.NewManager(tcpRest, controllerruntime.Options{
|
||||
Logger: log.Log.WithName(fmt.Sprintf("soot_%s_%s", tcp.GetNamespace(), tcp.GetName())),
|
||||
Scheme: m.client.Scheme(),
|
||||
MetricsBindAddress: "0",
|
||||
NewClient: func(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) {
|
||||
Logger: log.Log.WithName(fmt.Sprintf("soot_%s_%s", tcp.GetNamespace(), tcp.GetName())),
|
||||
Scheme: m.client.Scheme(),
|
||||
Metrics: metricsserver.Options{
|
||||
BindAddress: "0",
|
||||
},
|
||||
NewClient: func(config *rest.Config, options client.Options) (client.Client, error) {
|
||||
return client.New(config, client.Options{
|
||||
Scheme: m.client.Scheme(),
|
||||
})
|
||||
@@ -256,6 +258,17 @@ func (m *Manager) Reconcile(ctx context.Context, request reconcile.Request) (res
|
||||
if err = bootstrapToken.SetupWithManager(mgr); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
kubeadmRbac := &controllers.KubeadmPhase{
|
||||
GetTenantControlPlaneFunc: m.retrieveTenantControlPlane(tcpCtx, request),
|
||||
Phase: &resources.KubeadmPhase{
|
||||
Client: m.AdminClient,
|
||||
Phase: resources.PhaseClusterAdminRBAC,
|
||||
},
|
||||
}
|
||||
if err = kubeadmRbac.SetupWithManager(mgr); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
// Starting the manager
|
||||
go func() {
|
||||
if err = mgr.Start(tcpCtx); err != nil {
|
||||
@@ -289,7 +302,7 @@ func (m *Manager) SetupWithManager(mgr manager.Manager) error {
|
||||
m.sootMap = make(map[string]sootItem)
|
||||
|
||||
return controllerruntime.NewControllerManagedBy(mgr).
|
||||
Watches(&source.Channel{Source: m.sootManagerErrChan}, &handler.EnqueueRequestForObject{}).
|
||||
WatchesRawSource(&source.Channel{Source: m.sootManagerErrChan}, &handler.EnqueueRequestForObject{}).
|
||||
For(&kamajiv1alpha1.TenantControlPlane{}, builder.WithPredicates(predicate.NewPredicateFuncs(func(object client.Object) bool {
|
||||
obj := object.(*kamajiv1alpha1.TenantControlPlane) //nolint:forcetypeassert
|
||||
// status is required to understand if we have to start or stop the soot manager
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
apimachineryerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
"k8s.io/utils/clock"
|
||||
@@ -84,16 +84,15 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
defer cancelFn()
|
||||
|
||||
tenantControlPlane, err := r.getTenantControlPlane(ctx, req.NamespacedName)()
|
||||
if k8serrors.IsNotFound(err) {
|
||||
log.Info("resource have been deleted, skipping")
|
||||
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
if err != nil {
|
||||
if apimachineryerrors.IsNotFound(err) {
|
||||
log.Info("resource may have been deleted, skipping")
|
||||
log.Error(err, "cannot retrieve the required resource")
|
||||
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
log.Error(err, "cannot retrieve the required instance")
|
||||
|
||||
return ctrl.Result{}, err
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
releaser, err := mutex.Acquire(r.mutexSpec(tenantControlPlane))
|
||||
@@ -145,6 +144,7 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
tcpReconcilerConfig: r.Config,
|
||||
tenantControlPlane: *tenantControlPlane,
|
||||
connection: dsConnection,
|
||||
dataStore: *ds,
|
||||
}
|
||||
|
||||
for _, resource := range GetDeletableResources(tenantControlPlane, groupDeletableResourceBuilderConfiguration) {
|
||||
@@ -227,7 +227,7 @@ func (r *TenantControlPlaneReconciler) SetupWithManager(mgr ctrl.Manager) error
|
||||
r.clock = clock.RealClock{}
|
||||
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
Watches(&source.Channel{Source: r.CertificateChan}, handler.Funcs{GenericFunc: func(genericEvent event.GenericEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
WatchesRawSource(&source.Channel{Source: r.CertificateChan}, handler.Funcs{GenericFunc: func(_ context.Context, genericEvent event.GenericEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
limitingInterface.AddRateLimited(ctrl.Request{
|
||||
NamespacedName: k8stypes.NamespacedName{
|
||||
Namespace: genericEvent.Object.GetNamespace(),
|
||||
@@ -235,7 +235,7 @@ func (r *TenantControlPlaneReconciler) SetupWithManager(mgr ctrl.Manager) error
|
||||
},
|
||||
})
|
||||
}}).
|
||||
Watches(&source.Channel{Source: r.TriggerChan}, handler.Funcs{GenericFunc: func(genericEvent event.GenericEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
WatchesRawSource(&source.Channel{Source: r.TriggerChan}, handler.Funcs{GenericFunc: func(_ context.Context, genericEvent event.GenericEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
limitingInterface.AddRateLimited(ctrl.Request{
|
||||
NamespacedName: k8stypes.NamespacedName{
|
||||
Namespace: genericEvent.Object.GetNamespace(),
|
||||
@@ -249,7 +249,7 @@ func (r *TenantControlPlaneReconciler) SetupWithManager(mgr ctrl.Manager) error
|
||||
Owns(&appsv1.Deployment{}).
|
||||
Owns(&corev1.Service{}).
|
||||
Owns(&networkingv1.Ingress{}).
|
||||
Watches(&source.Kind{Type: &batchv1.Job{}}, handler.EnqueueRequestsFromMapFunc(func(object client.Object) []reconcile.Request {
|
||||
WatchesRawSource(source.Kind(mgr.GetCache(), &batchv1.Job{}), handler.EnqueueRequestsFromMapFunc(func(_ context.Context, object client.Object) []reconcile.Request {
|
||||
labels := object.GetLabels()
|
||||
|
||||
name, namespace := labels["tcp.kamaji.clastix.io/name"], labels["tcp.kamaji.clastix.io/namespace"]
|
||||
|
||||
@@ -86,6 +86,21 @@ helm install kamaji clastix/kamaji -n kamaji-system --create-namespace
|
||||
!!! note "A managed datastore is highly recommended in production"
|
||||
The [kamaji-etcd](https://github.com/clastix/kamaji-etcd) project provides the code to setup a multi-tenant `etcd` running as StatefulSet made of three replicas. Optionally, Kamaji offers support for a more robust storage system, as `MySQL` or `PostgreSQL` compatible database, thanks to the native [kine](https://github.com/k3s-io/kine) integration.
|
||||
|
||||
Now you should end up with a working Kamaji instance, including the default `datastore`:
|
||||
|
||||
```bash
|
||||
kubectl -n kamaji-system get pods
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
etcd-0 1/1 Running 0 50s
|
||||
etcd-1 1/1 Running 0 60s
|
||||
etcd-2 1/1 Running 0 90s
|
||||
kamaji-7949578bfb-lj44p 1/1 Running 0 12s
|
||||
```
|
||||
|
||||
> An unsuccessful first installation could fail for several reasons, such as missing a `StorageClass`, or even for a trivial `Ctrl+C` during the installation phase.
|
||||
>
|
||||
> See the [Cleanup](#cleanup) section before to retry an aborted installation.
|
||||
|
||||
## Create Tenant Cluster
|
||||
|
||||
### Tenant Control Plane
|
||||
@@ -319,7 +334,8 @@ tenant-00-worker-02 Ready <none> 2m32s v1.25.0
|
||||
```
|
||||
|
||||
## Cleanup
|
||||
Remove the worker nodes joined the tenant control plane
|
||||
### Delete a Tenant Cluster
|
||||
First, remove the worker nodes joined the tenant control plane
|
||||
|
||||
```bash
|
||||
kubectl --kubeconfig=${TENANT_NAMESPACE}-${TENANT_NAME}.kubeconfig delete nodes --all
|
||||
@@ -337,10 +353,37 @@ for i in "${!HOSTS[@]}"; do
|
||||
done
|
||||
```
|
||||
|
||||
Delete the tenant control plane from kamaji
|
||||
Delete the tenant control plane from Kamaji
|
||||
|
||||
```bash
|
||||
kubectl delete -f ${TENANT_NAMESPACE}-${TENANT_NAME}-tcp.yaml
|
||||
```
|
||||
|
||||
### Uninstall Kamaji
|
||||
Uninstall the Kamaji controller by removing the Helm release
|
||||
|
||||
```bash
|
||||
helm uninstall kamaji -n kamaji-system
|
||||
```
|
||||
|
||||
The default datastore installed three `etcd` replicas with persistent volumes, so remove the `PersistentVolumeClaims` resources:
|
||||
|
||||
```bash
|
||||
kubectl -n kamaji-system delete pvc --all
|
||||
```
|
||||
|
||||
Also delete the custom resources:
|
||||
|
||||
```bash
|
||||
kubectl delete crd tenantcontrolplanes.kamaji.clastix.io
|
||||
kubectl delete crd datastores.kamaji.clastix.io
|
||||
```
|
||||
|
||||
In case of a broken installation, manually remove the hooks installed by Kamaji:
|
||||
|
||||
```bash
|
||||
kubectl delete ValidatingWebhookConfiguration kamaji-validating-webhook-configuration
|
||||
kubectl delete MutatingWebhookConfiguration kamaji-mutating-webhook-configuration
|
||||
```
|
||||
|
||||
That's all folks!
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 163 KiB |
File diff suppressed because it is too large
Load Diff
@@ -12,3 +12,8 @@ In Kamaji, there are different components that might require independent version
|
||||
| v0.3.2 | v1.22+ | [v1.21.0 .. v1.27.3] |
|
||||
| v0.3.3 | v1.22+ | [v1.21.0 .. v1.27.3] |
|
||||
| v0.3.4 | v1.22+ | [v1.21.0 .. v1.28.1] |
|
||||
| v0.3.5 | v1.22+ | [v1.21.0 .. v1.28.1] |
|
||||
| v0.3.5 | v1.22+ | [v1.21.0 .. v1.28.1] |
|
||||
| v0.4.0 | v1.22+ | [v1.21.0 .. v1.29.0] |
|
||||
| v0.4.1 | v1.22+ | [v1.21.0 .. v1.29.1] |
|
||||
| v0.4.2 | v1.22+ | [v1.21.0 .. v1.29.1] |
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
@@ -44,7 +44,7 @@ var _ = BeforeSuite(func() {
|
||||
|
||||
By("bootstrapping test environment")
|
||||
testEnv = &envtest.Environment{
|
||||
UseExistingCluster: pointer.Bool(true),
|
||||
UseExistingCluster: pointer.To(true),
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -27,7 +27,7 @@ var _ = Describe("Deploy a TenantControlPlane resource with additional resources
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
AdditionalInitContainers: []corev1.Container{{
|
||||
Name: initContainerName,
|
||||
Image: initContainerImage,
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
@@ -43,7 +43,7 @@ var _ = Describe("Deploy a TenantControlPlane resource with additional options",
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
AdditionalInitContainers: []corev1.Container{{
|
||||
Name: initContainerName,
|
||||
Image: initContainerImage,
|
||||
@@ -256,7 +256,7 @@ var _ = Describe("Deploy a TenantControlPlane resource with additional options",
|
||||
}, &deploy)).NotTo(HaveOccurred())
|
||||
|
||||
return deploy.Spec.Template.Spec.InitContainers
|
||||
}, 10*time.Second, time.Second).Should(HaveLen(0), "Deployment should not contain anymore the init container")
|
||||
}, 10*time.Second, time.Second).Should(BeEmpty(), "Deployment should not contain anymore the init container")
|
||||
|
||||
Eventually(func() bool {
|
||||
deploy := appsv1.Deployment{}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
@@ -36,7 +36,7 @@ var _ = Describe("When migrating a Tenant Control Plane to another datastore", f
|
||||
DataStore: "etcd-bronze",
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "NodePort",
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -25,7 +25,7 @@ var _ = Describe("Deploy a TenantControlPlane resource with the MySQL driver", f
|
||||
DataStore: "mysql-bronze",
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -25,7 +25,7 @@ var _ = Describe("Deploy a TenantControlPlane resource with the PostgreSQL drive
|
||||
DataStore: "postgresql-bronze",
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -24,7 +24,7 @@ var _ = Describe("Deploy a TenantControlPlane resource", func() {
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -27,7 +27,7 @@ var _ = Describe("Deploy a TenantControlPlane with wrong preferred kubelet addre
|
||||
DataStore: "default",
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
@@ -63,7 +63,7 @@ var _ = Describe("Deploy a TenantControlPlane with wrong preferred kubelet addre
|
||||
DataStore: "default",
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -26,7 +26,7 @@ var _ = Describe("downgrade of a TenantControlPlane Kubernetes version", func()
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -26,7 +26,7 @@ var _ = Describe("non-linear minor upgrade of a TenantControlPlane Kubernetes ve
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/upgrade"
|
||||
@@ -36,7 +36,7 @@ var _ = Describe("using an unsupported TenantControlPlane Kubernetes version", f
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
@@ -64,7 +64,7 @@ var _ = Describe("using an unsupported TenantControlPlane Kubernetes version", f
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "ClusterIP",
|
||||
|
||||
@@ -19,9 +19,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
kubeadmv1beta3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -44,7 +44,7 @@ var _ = Describe("starting a kind worker with kubeadm", func() {
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "NodePort",
|
||||
@@ -121,7 +121,7 @@ var _ = Describe("starting a kind worker with kubeadm", func() {
|
||||
var joinCommandBuffer *bytes.Buffer
|
||||
|
||||
By("generating kubeadm join command", func() {
|
||||
joinCommandBuffer = bytes.NewBuffer([]byte(""))
|
||||
joinCommandBuffer = bytes.NewBufferString("")
|
||||
|
||||
config, err := clientcmd.BuildConfigFromFlags("", kubeconfigFile.Name())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@@ -129,7 +129,7 @@ var _ = Describe("starting a kind worker with kubeadm", func() {
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(cmd.RunCreateToken(joinCommandBuffer, clientset, "", util.DefaultInitConfiguration(), true, "", kubeconfigFile.Name())).ToNot(HaveOccurred())
|
||||
Expect(cmd.RunCreateToken(joinCommandBuffer, clientset, "", &kubeadmv1beta3.InitConfiguration{}, true, "", kubeconfigFile.Name())).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
By("executing the command in the worker node", func() {
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -39,7 +39,7 @@ var _ = Describe("validating kubeconfig", func() {
|
||||
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
||||
ControlPlane: kamajiv1alpha1.ControlPlane{
|
||||
Deployment: kamajiv1alpha1.DeploymentSpec{
|
||||
Replicas: pointer.Int32(1),
|
||||
Replicas: pointer.To(int32(1)),
|
||||
},
|
||||
Service: kamajiv1alpha1.ServiceSpec{
|
||||
ServiceType: "NodePort",
|
||||
|
||||
219
go.mod
219
go.mod
@@ -1,102 +1,96 @@
|
||||
module github.com/clastix/kamaji
|
||||
|
||||
go 1.18
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/JamesStewy/go-mysqldump v0.2.2
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/go-logr/logr v1.2.3
|
||||
github.com/go-logr/logr v1.3.0
|
||||
github.com/go-pg/pg/v10 v10.10.6
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/juju/mutex/v2 v2.0.0
|
||||
github.com/onsi/ginkgo/v2 v2.6.0
|
||||
github.com/onsi/gomega v1.24.1
|
||||
github.com/onsi/ginkgo/v2 v2.13.0
|
||||
github.com/onsi/gomega v1.29.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.10.1
|
||||
github.com/testcontainers/testcontainers-go v0.13.0
|
||||
go.etcd.io/etcd/api/v3 v3.5.6
|
||||
go.etcd.io/etcd/client/v3 v3.5.6
|
||||
go.etcd.io/etcd/api/v3 v3.5.10
|
||||
go.etcd.io/etcd/client/v3 v3.5.10
|
||||
go.uber.org/automaxprocs v1.5.1
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0
|
||||
k8s.io/api v0.26.1
|
||||
k8s.io/apimachinery v0.26.1
|
||||
k8s.io/apiserver v0.26.1
|
||||
k8s.io/client-go v0.26.1
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0
|
||||
k8s.io/api v0.29.1
|
||||
k8s.io/apimachinery v0.29.1
|
||||
k8s.io/apiserver v0.29.1
|
||||
k8s.io/client-go v0.29.1
|
||||
k8s.io/cluster-bootstrap v0.0.0
|
||||
k8s.io/klog/v2 v2.80.1
|
||||
k8s.io/klog/v2 v2.110.1
|
||||
k8s.io/kubelet v0.0.0
|
||||
k8s.io/kubernetes v1.26.1
|
||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448
|
||||
sigs.k8s.io/controller-runtime v0.14.0
|
||||
k8s.io/kubernetes v1.29.1
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||
sigs.k8s.io/controller-runtime v0.16.3
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.99.0 // indirect
|
||||
cloud.google.com/go/storage v1.18.2 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.17 // indirect
|
||||
github.com/Microsoft/hcsshim v0.8.23 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/Microsoft/hcsshim v0.8.25 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20211216145620-d92e9ce0af51 // indirect
|
||||
github.com/containerd/cgroups v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/containerd v1.5.9 // indirect
|
||||
github.com/coredns/caddy v1.1.0 // indirect
|
||||
github.com/coredns/corefile-migration v1.0.17 // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||
github.com/coredns/caddy v1.1.1 // indirect
|
||||
github.com/coredns/corefile-migration v1.0.21 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/distribution/reference v0.5.0 // indirect
|
||||
github.com/docker/distribution v2.8.1+incompatible // indirect
|
||||
github.com/docker/docker v20.10.11+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-logr/zapr v1.2.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-errors/errors v1.4.2 // indirect
|
||||
github.com/go-logr/zapr v1.2.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/go-pg/zerochecker v0.2.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/juju/errors v0.0.0-20220203013757-bd733f3c86b9 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/lithammer/dedent v1.1.0 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/moby/sys/mount v0.2.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
@@ -104,16 +98,16 @@ require (
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/runc v1.1.4 // indirect
|
||||
github.com/opencontainers/runc v1.1.10 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/spf13/afero v1.7.0 // indirect
|
||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
@@ -122,72 +116,77 @@ require (
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect
|
||||
github.com/vmihailenco/tagparser v0.1.2 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xlab/treeprint v1.1.0 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.1.0 // indirect
|
||||
golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/term v0.3.0 // indirect
|
||||
golang.org/x/text v0.5.0 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.25.0 // indirect
|
||||
golang.org/x/crypto v0.16.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/oauth2 v0.10.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/term v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/api v0.63.0 // indirect
|
||||
golang.org/x/tools v0.16.1 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect
|
||||
google.golang.org/grpc v1.49.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
google.golang.org/grpc v1.58.3 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.26.1 // indirect
|
||||
k8s.io/cli-runtime v0.26.1 // indirect
|
||||
k8s.io/component-base v0.26.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.29.1 // indirect
|
||||
k8s.io/cli-runtime v0.29.1 // indirect
|
||||
k8s.io/component-base v0.29.1 // indirect
|
||||
k8s.io/component-helpers v0.0.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
|
||||
k8s.io/kube-proxy v0.0.0 // indirect
|
||||
k8s.io/system-validators v1.8.0 // indirect
|
||||
mellium.im/sasl v0.3.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.12.1 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.26.1
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.1
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.26.1
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.26.1
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.1
|
||||
k8s.io/client-go => k8s.io/client-go v0.26.1
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.1
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.1
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.26.1
|
||||
k8s.io/component-base => k8s.io/component-base v0.26.1
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.26.1
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.26.1
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.26.1
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.1
|
||||
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.26.1
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.1
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.1
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.1
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.1
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.26.1
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.26.1
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.1
|
||||
k8s.io/metrics => k8s.io/metrics v0.26.1
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.26.1
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.26.1
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.1
|
||||
k8s.io/api => k8s.io/api v0.29.1
|
||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.29.1
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.29.1
|
||||
k8s.io/apiserver => k8s.io/apiserver v0.29.1
|
||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.29.1
|
||||
k8s.io/client-go => k8s.io/client-go v0.29.1
|
||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.29.1
|
||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.29.1
|
||||
k8s.io/code-generator => k8s.io/code-generator v0.29.1
|
||||
k8s.io/component-base => k8s.io/component-base v0.29.1
|
||||
k8s.io/component-helpers => k8s.io/component-helpers v0.29.1
|
||||
k8s.io/controller-manager => k8s.io/controller-manager v0.29.1
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.29.1
|
||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.29.1
|
||||
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.29.1
|
||||
k8s.io/endpointslice => k8s.io/endpointslice v0.29.1
|
||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.29.1
|
||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.29.1
|
||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.29.1
|
||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.29.1
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.29.1
|
||||
k8s.io/kubelet => k8s.io/kubelet v0.29.1
|
||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.29.1
|
||||
k8s.io/metrics => k8s.io/metrics v0.29.1
|
||||
k8s.io/mount-utils => k8s.io/mount-utils v0.29.1
|
||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.29.1
|
||||
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.29.1
|
||||
)
|
||||
|
||||
replace github.com/JamesStewy/go-mysqldump => github.com/vtoma/go-mysqldump v1.0.0
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
@@ -224,7 +224,7 @@ func (d Deployment) buildPKIVolume(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.T
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: sources,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -240,7 +240,7 @@ func (d Deployment) buildCAVolume(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.Te
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: tcp.Status.Certificates.CA.SecretName,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ func (d Deployment) buildSSLCertsVolume(podSpec *corev1.PodSpec, tcp kamajiv1alp
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: tcp.Status.Certificates.CA.SecretName,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -272,7 +272,7 @@ func (d Deployment) buildShareCAVolume(podSpec *corev1.PodSpec, tcp kamajiv1alph
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: tcp.Status.Certificates.CA.SecretName,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -288,7 +288,7 @@ func (d Deployment) buildLocalShareCAVolume(podSpec *corev1.PodSpec, tcp kamajiv
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: tcp.Status.Certificates.CA.SecretName,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -304,7 +304,7 @@ func (d Deployment) buildSchedulerVolume(podSpec *corev1.PodSpec, tcp kamajiv1al
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: tcp.Status.KubeConfig.Scheduler.SecretName,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -320,7 +320,7 @@ func (d Deployment) buildControllerManagerVolume(podSpec *corev1.PodSpec, tcp ka
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: tcp.Status.KubeConfig.ControllerManager.SecretName,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -727,7 +727,7 @@ func (d Deployment) buildKubeAPIServerCommand(tenantControlPlane kamajiv1alpha1.
|
||||
|
||||
// Order matters, here: extraArgs could try to overwrite some arguments managed by Kamaji and that would be crucial.
|
||||
// Adding as first element of the array of maps, we're sure that these overrides will be sanitized by our configuration.
|
||||
return utilities.MergeMaps(extraArgs, current, desiredArgs)
|
||||
return utilities.MergeMaps(current, desiredArgs, extraArgs)
|
||||
}
|
||||
|
||||
func (d Deployment) secretProjection(secretName, certKeyName, keyName string) *corev1.SecretProjection {
|
||||
@@ -776,7 +776,7 @@ func (d Deployment) buildKineVolume(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: tcp.Status.Storage.Certificate.SecretName,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
// Adding the volume to read Kine certificates:
|
||||
@@ -933,7 +933,7 @@ func (d Deployment) setReplicas(deploymentSpec *appsv1.DeploymentSpec, tcp kamaj
|
||||
|
||||
func (d Deployment) setRuntimeClass(spec *corev1.PodSpec, tcp kamajiv1alpha1.TenantControlPlane) {
|
||||
if len(tcp.Spec.ControlPlane.Deployment.RuntimeClassName) > 0 {
|
||||
spec.RuntimeClassName = pointer.String(tcp.Spec.ControlPlane.Deployment.RuntimeClassName)
|
||||
spec.RuntimeClassName = pointer.To(tcp.Spec.ControlPlane.Deployment.RuntimeClassName)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
@@ -186,7 +186,7 @@ func (k Konnectivity) buildVolumeMounts(podSpec *corev1.PodSpec) {
|
||||
|
||||
podSpec.Containers[index].Args = utilities.ArgsFromMapToSlice(args)
|
||||
|
||||
vFound, vIndex := false, 0
|
||||
vFound, vIndex := false, 0 //nolint:wastedassign
|
||||
// Patching the volume mounts
|
||||
if vFound, vIndex = utilities.HasNamedVolumeMount(podSpec.Containers[index].VolumeMounts, konnectivityUDSVolume); !vFound {
|
||||
vIndex = len(podSpec.Containers[index].VolumeMounts)
|
||||
@@ -208,9 +208,8 @@ func (k Konnectivity) buildVolumeMounts(podSpec *corev1.PodSpec) {
|
||||
}
|
||||
|
||||
func (k Konnectivity) buildVolumes(status kamajiv1alpha1.KonnectivityStatus, podSpec *corev1.PodSpec) {
|
||||
found, index := false, 0
|
||||
// Defining volumes for the UDS socket
|
||||
found, index = utilities.HasNamedVolume(podSpec.Volumes, konnectivityUDSVolume)
|
||||
found, index := utilities.HasNamedVolume(podSpec.Volumes, konnectivityUDSVolume)
|
||||
if !found {
|
||||
index = len(podSpec.Volumes)
|
||||
podSpec.Volumes = append(podSpec.Volumes, corev1.Volume{})
|
||||
@@ -235,7 +234,7 @@ func (k Konnectivity) buildVolumes(status kamajiv1alpha1.KonnectivityStatus, pod
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: status.ConfigMap.Name,
|
||||
},
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
// Defining volume for the Konnectivity kubeconfig
|
||||
@@ -249,7 +248,7 @@ func (k Konnectivity) buildVolumes(status kamajiv1alpha1.KonnectivityStatus, pod
|
||||
podSpec.Volumes[index].VolumeSource = corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: status.Kubeconfig.SecretName,
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func NewStorageConnection(ctx context.Context, client client.Client, ds kamajiv1
|
||||
return NewMySQLConnection(*cc)
|
||||
case kamajiv1alpha1.KinePostgreSQLDriver:
|
||||
cc.TLSConfig.ServerName = cc.Endpoints[0].Host
|
||||
//nolint:contextcheck
|
||||
|
||||
return NewPostgreSQLConnection(*cc)
|
||||
case kamajiv1alpha1.EtcdDriver:
|
||||
return NewETCDConnection(*cc)
|
||||
|
||||
@@ -136,7 +136,7 @@ func (e *EtcdClient) DeleteDB(ctx context.Context, dbName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EtcdClient) RevokePrivileges(ctx context.Context, user, dbName string) error {
|
||||
func (e *EtcdClient) RevokePrivileges(ctx context.Context, _, dbName string) error {
|
||||
if _, err := e.Client.Auth.RoleDelete(ctx, dbName); err != nil {
|
||||
return errors.NewRevokePrivilegesError(err)
|
||||
}
|
||||
|
||||
@@ -216,13 +216,17 @@ func (c *MySQLConnection) DBExists(ctx context.Context, dbName string) (bool, er
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
func (c *MySQLConnection) GrantPrivilegesExists(ctx context.Context, user, dbName string) (bool, error) {
|
||||
func (c *MySQLConnection) GrantPrivilegesExists(_ context.Context, user, dbName string) (bool, error) {
|
||||
statementShowGrantsStatement := fmt.Sprintf(mysqlShowGrantsStatement, user)
|
||||
rows, err := c.db.Query(statementShowGrantsStatement)
|
||||
rows, err := c.db.Query(statementShowGrantsStatement) //nolint:sqlclosecheck
|
||||
if err != nil {
|
||||
return false, errors.NewGrantPrivilegesError(err)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return false, errors.NewGrantPrivilegesError(err)
|
||||
}
|
||||
|
||||
expected := fmt.Sprintf(mysqlGrantPrivilegesStatement, user, dbName)
|
||||
var grant string
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ func (r *PostgreSQLConnection) Migrate(ctx context.Context, tcp kamajiv1alpha1.T
|
||||
// Dumping the old datastore in a local buffer
|
||||
var buf bytes.Buffer
|
||||
|
||||
if _, err := r.switchDatabaseFn(tcp.Status.Storage.Setup.Schema).WithContext(ctx).CopyTo(&buf, "COPY kine TO STDOUT"); err != nil { //nolint:contextcheck
|
||||
if _, err := r.switchDatabaseFn(tcp.Status.Storage.Setup.Schema).WithContext(ctx).CopyTo(&buf, "COPY kine TO STDOUT"); err != nil {
|
||||
return fmt.Errorf("unable to copy from the origin datastore: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ func GeneratePublicKeyPrivateKeyPair(baseName string, config *Configuration) (*P
|
||||
}
|
||||
|
||||
func initPhaseCertsSA(config *Configuration) error {
|
||||
return certs.CreateServiceAccountKeyAndPublicKeyFiles(config.InitConfiguration.CertificatesDir, config.InitConfiguration.PublicKeyAlgorithm())
|
||||
return certs.CreateServiceAccountKeyAndPublicKeyFiles(config.InitConfiguration.CertificatesDir, config.InitConfiguration.EncryptionAlgorithmType())
|
||||
}
|
||||
|
||||
func initPhaseFromCA(kubeadmCert *certs.KubeadmCert, config *Configuration, certificate *x509.Certificate, signer crypto.Signer) error {
|
||||
|
||||
@@ -64,9 +64,9 @@ func CreateKubeadmInitConfiguration(params Parameters) (*Configuration, error) {
|
||||
fmt.Sprintf("%s.%s.svc.cluster.local", params.TenantControlPlaneName, params.TenantControlPlaneNamespace),
|
||||
params.TenantControlPlaneAddress,
|
||||
}, params.TenantControlPlaneCertSANs...)
|
||||
conf.APIServer.ControlPlaneComponent.ExtraArgs = map[string]string{
|
||||
"etcd-compaction-interval": "0s",
|
||||
"etcd-prefix": fmt.Sprintf("/%s", params.TenantControlPlaneName),
|
||||
conf.APIServer.ControlPlaneComponent.ExtraArgs = []kubeadmapi.Arg{
|
||||
{Name: "etcd-compaction-interval", Value: "0s"},
|
||||
{Name: "etcd-prefix", Value: fmt.Sprintf("/%s", params.TenantControlPlaneName)},
|
||||
}
|
||||
conf.ClusterName = params.TenantControlPlaneName
|
||||
|
||||
|
||||
@@ -26,11 +26,8 @@ func buildCertificateDirectoryWithCA(ca CertificatePrivateKeyPair, directory str
|
||||
}
|
||||
|
||||
keyPath := path.Join(directory, kubeadmconstants.CAKeyName)
|
||||
if err := os.WriteFile(keyPath, ca.PrivateKey, os.FileMode(0o600)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return os.WriteFile(keyPath, ca.PrivateKey, os.FileMode(0o600))
|
||||
}
|
||||
|
||||
func CreateKubeconfig(kubeconfigName string, ca CertificatePrivateKeyPair, config *Configuration) ([]byte, error) {
|
||||
|
||||
@@ -11,28 +11,28 @@ import (
|
||||
|
||||
type Discard struct{}
|
||||
|
||||
func (d Discard) PrintObj(obj runtime.Object, writer io.Writer) error {
|
||||
func (d Discard) PrintObj(runtime.Object, io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d Discard) Fprintf(writer io.Writer, format string, args ...interface{}) (n int, err error) {
|
||||
func (d Discard) Fprintf(io.Writer, string, ...interface{}) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (d Discard) Fprintln(writer io.Writer, args ...interface{}) (n int, err error) {
|
||||
func (d Discard) Fprintln(io.Writer, ...interface{}) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (d Discard) Printf(format string, args ...interface{}) (n int, err error) {
|
||||
func (d Discard) Printf(string, ...interface{}) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (d Discard) Println(args ...interface{}) (n int, err error) {
|
||||
func (d Discard) Println(...interface{}) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (d Discard) Flush(writer io.Writer, last bool) {
|
||||
func (d Discard) Flush(io.Writer, bool) {
|
||||
}
|
||||
|
||||
func (d Discard) Close(writer io.Writer) {
|
||||
func (d Discard) Close(io.Writer) {
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
@@ -81,10 +81,10 @@ func getKubeletConfigmapContent(kubeletConfiguration KubeletConfiguration) ([]by
|
||||
},
|
||||
Authentication: kubelettypes.KubeletAuthentication{
|
||||
Anonymous: kubelettypes.KubeletAnonymousAuthentication{
|
||||
Enabled: pointer.Bool(false),
|
||||
Enabled: pointer.To(false),
|
||||
},
|
||||
Webhook: kubelettypes.KubeletWebhookAuthentication{
|
||||
Enabled: pointer.Bool(true),
|
||||
Enabled: pointer.To(true),
|
||||
CacheTTL: zeroDuration,
|
||||
},
|
||||
X509: kubelettypes.KubeletX509Authentication{
|
||||
@@ -110,9 +110,9 @@ func getKubeletConfigmapContent(kubeletConfiguration KubeletConfiguration) ([]by
|
||||
EvictionPressureTransitionPeriod: zeroDuration,
|
||||
FileCheckFrequency: zeroDuration,
|
||||
HealthzBindAddress: "127.0.0.1",
|
||||
HealthzPort: pointer.Int32(10248),
|
||||
HealthzPort: pointer.To(int32(10248)),
|
||||
HTTPCheckFrequency: zeroDuration,
|
||||
ImageGCHighThresholdPercent: pointer.Int32(100),
|
||||
ImageGCHighThresholdPercent: pointer.To(int32(100)),
|
||||
NodeStatusUpdateFrequency: zeroDuration,
|
||||
NodeStatusReportFrequency: zeroDuration,
|
||||
RotateCertificates: true,
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
@@ -287,7 +287,7 @@ func (k *KubeProxy) mutateDaemonSet(ctx context.Context, tenantClient client.Cli
|
||||
ds.Spec.Template.Spec.Volumes[0].Name = k.daemonSet.Spec.Template.Spec.Volumes[0].Name
|
||||
ds.Spec.Template.Spec.Volumes[0].VolumeSource.ConfigMap = &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: k.daemonSet.Spec.Template.Spec.Volumes[0].VolumeSource.ConfigMap.Name},
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
}
|
||||
|
||||
ds.Spec.Template.Spec.Volumes[1].Name = k.daemonSet.Spec.Template.Spec.Volumes[1].Name
|
||||
|
||||
@@ -43,7 +43,7 @@ func (d *Migrate) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1
|
||||
|
||||
d.job = &batchv1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("migrate-%s-%s", tenantControlPlane.GetNamespace(), tenantControlPlane.GetName()),
|
||||
Name: fmt.Sprintf("migrate-%s", tenantControlPlane.UID),
|
||||
Namespace: d.KamajiNamespace,
|
||||
},
|
||||
}
|
||||
@@ -64,11 +64,8 @@ func (d *Migrate) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1
|
||||
}
|
||||
|
||||
d.desiredDatastore = &kamajiv1alpha1.DataStore{}
|
||||
if err := d.Client.Get(ctx, types.NamespacedName{Name: tenantControlPlane.Spec.DataStore}, d.desiredDatastore); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return d.Client.Get(ctx, types.NamespacedName{Name: tenantControlPlane.Spec.DataStore}, d.desiredDatastore)
|
||||
}
|
||||
|
||||
func (d *Migrate) ShouldCleanup(tcp *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
|
||||
@@ -9,13 +9,18 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kubeerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/controllers/finalizers"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
|
||||
@@ -62,6 +67,30 @@ func (r *Config) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv
|
||||
return utilities.CreateOrUpdateWithConflict(ctx, r.Client, r.resource, r.mutate(ctx, tenantControlPlane))
|
||||
}
|
||||
|
||||
func (r *Config) Delete(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) error {
|
||||
secret := r.resource.DeepCopy()
|
||||
|
||||
if err := r.Client.Get(ctx, types.NamespacedName{Name: r.resource.Name, Namespace: r.resource.Namespace}, secret); err != nil {
|
||||
if kubeerrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.Wrap(err, "cannot retrieve the DataStore Secret for removal")
|
||||
}
|
||||
|
||||
secret.SetFinalizers(nil)
|
||||
|
||||
if err := r.Client.Update(ctx, secret); err != nil {
|
||||
if kubeerrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.Wrap(err, "cannot remove DataStore Secret finalizers")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Config) GetName() string {
|
||||
return "datastore-config"
|
||||
}
|
||||
@@ -100,6 +129,10 @@ func (r *Config) mutate(_ context.Context, tenantControlPlane *kamajiv1alpha1.Te
|
||||
return []byte(strings.ReplaceAll(fmt.Sprintf("%s_%s", tenantControlPlane.GetNamespace(), tenantControlPlane.GetName()), "-", "_"))
|
||||
}
|
||||
|
||||
finalizersList := sets.New[string](r.resource.GetFinalizers()...)
|
||||
finalizersList.Insert(finalizers.DatastoreSecretFinalizer)
|
||||
r.resource.SetFinalizers(finalizersList.UnsortedList())
|
||||
|
||||
r.resource.Data = map[string][]byte{
|
||||
"DB_CONNECTION_STRING": []byte(r.ConnString),
|
||||
"DB_SCHEMA": coalesceFn(tenantControlPlane.Status.Storage.Setup.Schema),
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
@@ -119,7 +119,7 @@ func (r *KubernetesIngressResource) mutate(tenantControlPlane *kamajiv1alpha1.Te
|
||||
}
|
||||
|
||||
path.Path = "/"
|
||||
path.PathType = (*networkingv1.PathType)(pointer.String(string(networkingv1.PathTypePrefix)))
|
||||
path.PathType = (*networkingv1.PathType)(pointer.To(string(networkingv1.PathTypePrefix)))
|
||||
|
||||
if path.Backend.Service == nil {
|
||||
path.Backend.Service = &networkingv1.IngressServiceBackend{}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
@@ -146,11 +146,11 @@ func (r *Agent) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.T
|
||||
ServiceAccountToken: &corev1.ServiceAccountTokenProjection{
|
||||
Path: agentTokenName,
|
||||
Audience: tenantControlPlane.Status.Addons.Konnectivity.ClusterRoleBinding.Name,
|
||||
ExpirationSeconds: pointer.Int64(3600),
|
||||
ExpirationSeconds: pointer.To(int64(3600)),
|
||||
},
|
||||
},
|
||||
},
|
||||
DefaultMode: pointer.Int32(420),
|
||||
DefaultMode: pointer.To(int32(420)),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -164,8 +164,7 @@ func (r *Agent) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.T
|
||||
r.resource.Spec.Template.Spec.Containers[0].Name = AgentName
|
||||
r.resource.Spec.Template.Spec.Containers[0].Command = []string{"/proxy-agent"}
|
||||
|
||||
args := utilities.ArgsFromSliceToMap(tenantControlPlane.Spec.Addons.Konnectivity.KonnectivityAgentSpec.ExtraArgs)
|
||||
|
||||
args := make(map[string]string)
|
||||
args["-v"] = "8"
|
||||
args["--logtostderr"] = "true"
|
||||
args["--ca-cert"] = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
||||
@@ -175,6 +174,12 @@ func (r *Agent) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.T
|
||||
args["--health-server-port"] = "8134"
|
||||
args["--service-account-token-path"] = "/var/run/secrets/tokens/konnectivity-agent-token"
|
||||
|
||||
extraArgs := utilities.ArgsFromSliceToMap(tenantControlPlane.Spec.Addons.Konnectivity.KonnectivityAgentSpec.ExtraArgs)
|
||||
|
||||
for k, v := range extraArgs {
|
||||
args[k] = v
|
||||
}
|
||||
|
||||
r.resource.Spec.Template.Spec.Containers[0].Args = utilities.ArgsFromMapToSlice(args)
|
||||
r.resource.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ type CertificateResource struct {
|
||||
Client client.Client
|
||||
}
|
||||
|
||||
func (r *CertificateResource) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
func (r *CertificateResource) ShouldStatusBeUpdated(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Status.Addons.Konnectivity.Certificate.Checksum != utilities.GetObjectChecksum(r.resource)
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func (r *CertificateResource) GetName() string {
|
||||
return "konnectivity-certificate"
|
||||
}
|
||||
|
||||
func (r *CertificateResource) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
func (r *CertificateResource) UpdateTenantControlPlaneStatus(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
if tenantControlPlane.Spec.Addons.Konnectivity != nil {
|
||||
tenantControlPlane.Status.Addons.Konnectivity.Certificate.LastUpdate = metav1.Now()
|
||||
tenantControlPlane.Status.Addons.Konnectivity.Certificate.SecretName = r.resource.GetName()
|
||||
|
||||
@@ -24,7 +24,7 @@ type EgressSelectorConfigurationResource struct {
|
||||
Client client.Client
|
||||
}
|
||||
|
||||
func (r *EgressSelectorConfigurationResource) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
func (r *EgressSelectorConfigurationResource) Define(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
r.resource = &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: utilities.AddTenantPrefix(r.GetName(), tenantControlPlane),
|
||||
@@ -39,7 +39,7 @@ func (r *EgressSelectorConfigurationResource) ShouldCleanup(tenantControlPlane *
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
}
|
||||
|
||||
func (r *EgressSelectorConfigurationResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
func (r *EgressSelectorConfigurationResource) CleanUp(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
|
||||
if err := r.Client.Delete(ctx, r.resource); err != nil {
|
||||
@@ -63,11 +63,11 @@ func (r *EgressSelectorConfigurationResource) GetName() string {
|
||||
return "konnectivity-egress-selector-configuration"
|
||||
}
|
||||
|
||||
func (r *EgressSelectorConfigurationResource) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
func (r *EgressSelectorConfigurationResource) ShouldStatusBeUpdated(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Status.Addons.Konnectivity.ConfigMap.Checksum != utilities.GetObjectChecksum(r.resource)
|
||||
}
|
||||
|
||||
func (r *EgressSelectorConfigurationResource) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
func (r *EgressSelectorConfigurationResource) UpdateTenantControlPlaneStatus(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
if tenantControlPlane.Spec.Addons.Konnectivity != nil {
|
||||
tenantControlPlane.Status.Addons.Konnectivity.ConfigMap.Name = r.resource.GetName()
|
||||
tenantControlPlane.Status.Addons.Konnectivity.ConfigMap.Checksum = utilities.GetObjectChecksum(r.resource)
|
||||
|
||||
@@ -61,7 +61,7 @@ func (r *KubeadmConfigResource) GetName() string {
|
||||
return "kubeadmconfig"
|
||||
}
|
||||
|
||||
func (r *KubeadmConfigResource) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
func (r *KubeadmConfigResource) UpdateTenantControlPlaneStatus(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
tenantControlPlane.Status.KubeadmConfig.LastUpdate = metav1.Now()
|
||||
tenantControlPlane.Status.KubeadmConfig.Checksum = utilities.GetObjectChecksum(r.resource)
|
||||
tenantControlPlane.Status.KubeadmConfig.ConfigmapName = r.resource.GetName()
|
||||
@@ -116,10 +116,6 @@ func (r *KubeadmConfigResource) mutate(ctx context.Context, tenantControlPlane *
|
||||
|
||||
utilities.SetObjectChecksum(r.resource, r.resource.Data)
|
||||
|
||||
if err := ctrl.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return ctrl.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,17 @@ package resources
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
@@ -27,10 +32,11 @@ const (
|
||||
PhaseUploadConfigKubeadm kubeadmPhase = iota
|
||||
PhaseUploadConfigKubelet
|
||||
PhaseBootstrapToken
|
||||
PhaseClusterAdminRBAC
|
||||
)
|
||||
|
||||
func (d kubeadmPhase) String() string {
|
||||
return [...]string{"PhaseUploadConfigKubeadm", "PhaseUploadConfigKubelet", "PhaseBootstrapToken"}[d]
|
||||
return [...]string{"PhaseUploadConfigKubeadm", "PhaseUploadConfigKubelet", "PhaseBootstrapToken", "PhaseClusterAdminRBAC"}[d]
|
||||
}
|
||||
|
||||
type KubeadmPhase struct {
|
||||
@@ -47,6 +53,8 @@ func (r *KubeadmPhase) GetWatchedObject() client.Object {
|
||||
return &corev1.ConfigMap{}
|
||||
case PhaseBootstrapToken:
|
||||
return &corev1.Secret{}
|
||||
case PhaseClusterAdminRBAC:
|
||||
return &rbacv1.ClusterRoleBinding{}
|
||||
default:
|
||||
panic("shouldn't happen")
|
||||
}
|
||||
@@ -56,11 +64,11 @@ func (r *KubeadmPhase) GetPredicateFunc() func(obj client.Object) bool {
|
||||
switch r.Phase {
|
||||
case PhaseUploadConfigKubeadm:
|
||||
return func(obj client.Object) bool {
|
||||
return obj.GetName() == constants.KubeadmConfigConfigMap && obj.GetNamespace() == metav1.NamespaceSystem
|
||||
return obj.GetName() == kubeadmconstants.KubeadmConfigConfigMap && obj.GetNamespace() == metav1.NamespaceSystem
|
||||
}
|
||||
case PhaseUploadConfigKubelet:
|
||||
return func(obj client.Object) bool {
|
||||
return obj.GetName() == constants.KubeletBaseConfigurationConfigMap && obj.GetNamespace() == metav1.NamespaceSystem
|
||||
return obj.GetName() == kubeadmconstants.KubeletBaseConfigurationConfigMap && obj.GetNamespace() == metav1.NamespaceSystem
|
||||
}
|
||||
case PhaseBootstrapToken:
|
||||
return func(obj client.Object) bool {
|
||||
@@ -68,6 +76,12 @@ func (r *KubeadmPhase) GetPredicateFunc() func(obj client.Object) bool {
|
||||
|
||||
return secret.Type == "bootstrap.kubernetes.io/token" && secret.GetNamespace() == metav1.NamespaceSystem
|
||||
}
|
||||
case PhaseClusterAdminRBAC:
|
||||
return func(obj client.Object) bool {
|
||||
cr := obj.(*rbacv1.ClusterRoleBinding) //nolint:forcetypeassert
|
||||
|
||||
return strings.HasPrefix(cr.Name, "kubeadm:")
|
||||
}
|
||||
default:
|
||||
panic("shouldn't happen")
|
||||
}
|
||||
@@ -107,7 +121,7 @@ func (r *KubeadmPhase) Define(context.Context, *kamajiv1alpha1.TenantControlPlan
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *KubeadmPhase) GetKubeadmFunction() (func(clientset.Interface, *kubeadm.Configuration) ([]byte, error), error) {
|
||||
func (r *KubeadmPhase) GetKubeadmFunction(ctx context.Context, tcp *kamajiv1alpha1.TenantControlPlane) (func(clientset.Interface, *kubeadm.Configuration) ([]byte, error), error) {
|
||||
switch r.Phase {
|
||||
case PhaseUploadConfigKubeadm:
|
||||
return kubeadm.UploadKubeadmConfig, nil
|
||||
@@ -119,6 +133,43 @@ func (r *KubeadmPhase) GetKubeadmFunction() (func(clientset.Interface, *kubeadm.
|
||||
|
||||
return nil, kubeadm.BootstrapToken(client, config)
|
||||
}, nil
|
||||
case PhaseClusterAdminRBAC:
|
||||
return func(c clientset.Interface, configuration *kubeadm.Configuration) ([]byte, error) {
|
||||
tmp, err := os.MkdirTemp("", string(tcp.UID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func() { _ = os.Remove(tmp) }()
|
||||
|
||||
var caSecret corev1.Secret
|
||||
|
||||
if err = r.Client.Get(ctx, types.NamespacedName{Name: tcp.Status.Certificates.CA.SecretName, Namespace: tcp.Namespace}, &caSecret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
crtKeyPair := kubeadm.CertificatePrivateKeyPair{
|
||||
Certificate: caSecret.Data[kubeadmconstants.CACertName],
|
||||
PrivateKey: caSecret.Data[kubeadmconstants.CAKeyName],
|
||||
}
|
||||
|
||||
for _, i := range []string{AdminKubeConfigFileName, SuperAdminKubeConfigFileName} {
|
||||
configuration.InitConfiguration.CertificatesDir, _ = os.MkdirTemp(tmp, "")
|
||||
|
||||
kubeconfigValue, err := kubeadm.CreateKubeconfig(SuperAdminKubeConfigFileName, crtKeyPair, configuration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_ = os.WriteFile(fmt.Sprintf("%s/%s", tmp, i), kubeconfigValue, os.ModePerm)
|
||||
}
|
||||
|
||||
if _, err = kubeconfig.EnsureAdminClusterRoleBinding(tmp, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("no available functionality for phase %s", r.Phase)
|
||||
}
|
||||
@@ -175,7 +226,7 @@ func (r *KubeadmPhase) UpdateTenantControlPlaneStatus(ctx context.Context, tenan
|
||||
|
||||
func (r *KubeadmPhase) GetStatus(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (kamajiv1alpha1.KubeadmConfigChecksumDependant, error) {
|
||||
switch r.Phase {
|
||||
case PhaseUploadConfigKubeadm, PhaseUploadConfigKubelet:
|
||||
case PhaseUploadConfigKubeadm, PhaseUploadConfigKubelet, PhaseClusterAdminRBAC:
|
||||
return nil, nil
|
||||
case PhaseBootstrapToken:
|
||||
return &tenantControlPlane.Status.KubeadmPhase.BootstrapToken, nil
|
||||
|
||||
@@ -142,7 +142,7 @@ func KubeadmPhaseCreate(ctx context.Context, r KubeadmPhaseResource, logger logr
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
fun, err := r.GetKubeadmFunction()
|
||||
fun, err := r.GetKubeadmFunction(ctx, tenantControlPlane)
|
||||
if err != nil {
|
||||
logger.Error(err, "cannot retrieve kubeadm function")
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package resources
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -24,6 +25,7 @@ import (
|
||||
|
||||
const (
|
||||
AdminKubeConfigFileName = kubeadmconstants.AdminKubeConfigFileName
|
||||
SuperAdminKubeConfigFileName = kubeadmconstants.SuperAdminKubeConfigFileName
|
||||
ControllerManagerKubeConfigFileName = kubeadmconstants.ControllerManagerKubeConfigFileName
|
||||
SchedulerKubeConfigFileName = kubeadmconstants.SchedulerKubeConfigFileName
|
||||
localhost = "127.0.0.1"
|
||||
@@ -56,7 +58,7 @@ func (r *KubeconfigResource) CleanUp(context.Context, *kamajiv1alpha1.TenantCont
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (r *KubeconfigResource) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
func (r *KubeconfigResource) Define(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
r.resource = &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: r.getPrefixedName(tenantControlPlane),
|
||||
@@ -102,7 +104,7 @@ func (r *KubeconfigResource) UpdateTenantControlPlaneStatus(ctx context.Context,
|
||||
|
||||
func (r *KubeconfigResource) getKubeconfigStatus(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*kamajiv1alpha1.KubeconfigStatus, error) {
|
||||
switch r.KubeConfigFileName {
|
||||
case kubeadmconstants.AdminKubeConfigFileName:
|
||||
case kubeadmconstants.AdminKubeConfigFileName, kubeadmconstants.SuperAdminKubeConfigFileName:
|
||||
return &tenantControlPlane.Status.KubeConfig.Admin, nil
|
||||
case kubeadmconstants.ControllerManagerKubeConfigFileName:
|
||||
return &tenantControlPlane.Status.KubeConfig.ControllerManager, nil
|
||||
@@ -125,6 +127,7 @@ func (r *KubeconfigResource) checksum(caCertificatesSecret *corev1.Secret, kubea
|
||||
})
|
||||
}
|
||||
|
||||
//nolint:gocognit
|
||||
func (r *KubeconfigResource) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) controllerutil.MutateFn {
|
||||
return func() error {
|
||||
logger := log.FromContext(ctx, "resource", r.GetName())
|
||||
@@ -181,12 +184,21 @@ func (r *KubeconfigResource) mutate(ctx context.Context, tenantControlPlane *kam
|
||||
shouldCreate = shouldCreate || !kubeadm.IsKubeconfigValid(r.resource.Data[r.KubeConfigFileName]) // invalid kubeconfig, or expired client certificate
|
||||
shouldCreate = shouldCreate || status.Checksum != checksum || len(r.resource.UID) == 0 // Wrong checksum
|
||||
|
||||
if !shouldCreate {
|
||||
v, ok := r.resource.Data[r.KubeConfigFileName]
|
||||
shouldCreate = len(v) == 0 || !ok
|
||||
}
|
||||
//nolint:nestif
|
||||
if shouldCreate {
|
||||
crtKeyPair := kubeadm.CertificatePrivateKeyPair{
|
||||
Certificate: caCertificatesSecret.Data[kubeadmconstants.CACertName],
|
||||
PrivateKey: caCertificatesSecret.Data[kubeadmconstants.CAKeyName],
|
||||
}
|
||||
|
||||
if r.resource.Data == nil {
|
||||
r.resource.Data = map[string][]byte{}
|
||||
}
|
||||
|
||||
kubeconfig, kcErr := kubeadm.CreateKubeconfig(r.KubeConfigFileName, crtKeyPair, config)
|
||||
if kcErr != nil {
|
||||
logger.Error(kcErr, "cannot create a valid kubeconfig")
|
||||
@@ -194,8 +206,23 @@ func (r *KubeconfigResource) mutate(ctx context.Context, tenantControlPlane *kam
|
||||
return kcErr
|
||||
}
|
||||
|
||||
r.resource.Data = map[string][]byte{
|
||||
r.KubeConfigFileName: kubeconfig,
|
||||
r.resource.Data[r.KubeConfigFileName] = kubeconfig
|
||||
// Adding a kubeconfig useful for the local connections:
|
||||
// especially for the admin.conf and super-admin.conf, these would use the public IP address.
|
||||
// However, when running in-cluster agents, it would be beneficial having a local connection
|
||||
// to avoid unnecessary hops to the LB.
|
||||
if strings.Contains(r.KubeConfigFileName, "admin") {
|
||||
key := strings.ReplaceAll(r.KubeConfigFileName, ".conf", ".svc")
|
||||
|
||||
config.InitConfiguration.ControlPlaneEndpoint = fmt.Sprintf("%s.%s.svc:%d", tenantControlPlane.Name, tenantControlPlane.Namespace, tenantControlPlane.Spec.NetworkProfile.Port)
|
||||
kubeconfig, kcErr = kubeadm.CreateKubeconfig(r.KubeConfigFileName, crtKeyPair, config)
|
||||
if kcErr != nil {
|
||||
logger.Error(kcErr, "cannot create a valid kubeconfig")
|
||||
|
||||
return kcErr
|
||||
}
|
||||
|
||||
r.resource.Data[key] = kubeconfig
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ type KubeadmPhaseResource interface {
|
||||
Resource
|
||||
KubeadmResource
|
||||
GetClient() client.Client
|
||||
GetKubeadmFunction() (func(clientset.Interface, *kubeadm.Configuration) ([]byte, error), error)
|
||||
GetKubeadmFunction(context.Context, *kamajiv1alpha1.TenantControlPlane) (func(clientset.Interface, *kubeadm.Configuration) ([]byte, error), error)
|
||||
GetStatus(*kamajiv1alpha1.TenantControlPlane) (kamajiv1alpha1.KubeadmConfigChecksumDependant, error)
|
||||
SetKubeadmConfigChecksum(string)
|
||||
GetWatchedObject() client.Object
|
||||
|
||||
@@ -5,7 +5,6 @@ package utils
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
)
|
||||
@@ -33,7 +32,6 @@ func UpdateOperationResult(current controllerutil.OperationResult, op controller
|
||||
}
|
||||
|
||||
func RandomString(n int) string {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
package upgrade
|
||||
|
||||
const (
|
||||
KubeadmVersion = "v1.28.1"
|
||||
KubeadmVersion = "v1.29.1"
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ func GetTenantKubeconfig(ctx context.Context, client client.Client, tenantContro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return DecodeKubeconfig(*secretKubeconfig, kubeadmconstants.AdminKubeConfigFileName)
|
||||
return DecodeKubeconfig(*secretKubeconfig, kubeadmconstants.SuperAdminKubeConfigFileName)
|
||||
}
|
||||
|
||||
func GetRESTClientConfig(ctx context.Context, client client.Client, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*restclient.Config, error) {
|
||||
|
||||
@@ -70,7 +70,7 @@ func DecodeFromYAML(o string, to runtime.Object) (err error) {
|
||||
Strict: false,
|
||||
})
|
||||
|
||||
if to, _, err = encoder.Decode([]byte(o), nil, to); err != nil { //nolint:ineffassign,staticcheck
|
||||
if to, _, err = encoder.Decode([]byte(o), nil, to); err != nil { //nolint:ineffassign,staticcheck,wastedassign
|
||||
return
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func DecodeFromJSON(o string, to runtime.Object) (err error) {
|
||||
Strict: false,
|
||||
})
|
||||
|
||||
if to, _, err = encoder.Decode([]byte(o), nil, to); err != nil { //nolint:ineffassign,staticcheck
|
||||
if to, _, err = encoder.Decode([]byte(o), nil, to); err != nil { //nolint:ineffassign,staticcheck,wastedassign
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -68,11 +68,7 @@ func (d DataStoreValidation) validate(ctx context.Context, ds kamajiv1alpha1.Dat
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.validateTLSConfig(ctx, ds); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return d.validateTLSConfig(ctx, ds)
|
||||
}
|
||||
|
||||
func (d DataStoreValidation) validateBasicAuth(ctx context.Context, ds kamajiv1alpha1.DataStore) error {
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/utils/pointer"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
@@ -37,7 +37,7 @@ func (t TenantControlPlaneDefaults) OnCreate(object runtime.Object) AdmissionRes
|
||||
}
|
||||
|
||||
if tcp.Spec.ControlPlane.Deployment.Replicas == nil {
|
||||
tcp.Spec.ControlPlane.Deployment.Replicas = pointer.Int32(2)
|
||||
tcp.Spec.ControlPlane.Deployment.Replicas = pointer.To(int32(2))
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
@@ -61,7 +61,7 @@ func (t TenantControlPlaneDefaults) OnUpdate(object runtime.Object, oldObject ru
|
||||
}
|
||||
|
||||
if newTCP.Spec.ControlPlane.Deployment.Replicas == nil {
|
||||
newTCP.Spec.ControlPlane.Deployment.Replicas = pointer.Int32(2)
|
||||
newTCP.Spec.ControlPlane.Deployment.Replicas = pointer.To(int32(2))
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
@@ -16,13 +15,8 @@ import (
|
||||
func Register(mgr controllerruntime.Manager, routes map[webhookroutes.Route][]webhookhandlers.Handler) error {
|
||||
srv := mgr.GetWebhookServer()
|
||||
|
||||
decoder, err := admission.NewDecoder(mgr.GetScheme())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to create NewDecoder for webhook registration")
|
||||
}
|
||||
|
||||
chainer := handlersChainer{
|
||||
decoder: decoder,
|
||||
decoder: admission.NewDecoder(mgr.GetScheme()),
|
||||
}
|
||||
|
||||
for route, handlers := range routes {
|
||||
|
||||
Reference in New Issue
Block a user