Added support for configuration per project

Shoots with type==Infrastructure will not be considered to be added to Fleet
This commit is contained in:
Jakub Vavřík
2021-02-18 08:08:06 +01:00
parent 46ab0c5eae
commit d2d7872f67
16 changed files with 378 additions and 117 deletions

View File

@@ -76,7 +76,7 @@ revendor:
@GO111MODULE=on go mod vendor
@GO111MODULE=on go mod tidy
@chmod +x $(REPO_ROOT)/vendor/github.com/gardener/gardener/hack/*
@chmod +x $(REPO_ROOT)/vendor/github.com/gardener/gardener/hack/.ci/*
@chmod +x $(REPO_ROOT)/vendor/github. com/gardener/gardener/hack/.ci/*
@$(REPO_ROOT)/hack/update-github-templates.sh
.PHONY: clean

View File

@@ -11,17 +11,30 @@ Recently, most of the vendor specific logic has been developed [in-tree](https:/
## Configuration
Example configuration for this extension controller:
Example configuration for this extension controller with default config and 2 project specific configs:
```yaml
apiVersion: shoot-fleet-agent-service.extensions.config.gardener.cloud/v1alpha1
kind: Configuration
clientConnection:
defaultConfig:
kubeconfig: #base64encoded kubeconfig of cluster running Fleet manager
labels: #extra labels to apply to Cluster registration
env: dev
env: dev
projectConfig:
myproject:
kubeconfig: #base64encoded kubeconfig of cluster running Fleet manager
labels:
project: myproject
somelabel: samevalue
namespace: clusters
myotherproject:
kubeconfig: #base64encoded kubeconfig of cluster running Fleet manager
labels:
project: mypotherproject
namespace: fleetclusters
```
Unless the shoot is in one of the myproject or myother project it will get defaultConfiguration.
Configuration supplied in ControllerRegistration will be applied as default however it can be overriden via configuration in Extension for given Shoot.
## Extension-Resources
Example extension resource:
@@ -39,6 +52,22 @@ spec:
When an extension resource is reconciled, the extension controller will register Shoot cluster in Fleet management cluster(configured in kubeconfig in Configuration object above.
Please note, this extension controller relies on existing properly configured [Fleet multi-cluster deployment](https://fleet.rancher.io/multi-cluster-install/) configured above.
By default configuration from ControllerRegistration is used but if Extension specifies different config for particular Shoot that configuration overrides the default settings.
## Shooted seeds registration in Fleet
All shooted seeds will be ignored and not registered in Fleet. If you need to register shooted seeds please do so manually.
## Fleet CRD cluster default labels
By default all clusters registered in fleet will have following labels:
|label|value|
|---|---|
|corebundle|true|
|region| region of shoot |
|cluster| name of shoot|
|seed|name of shoots seed|
Any labels defined in configuration are added to those default labels.
## How to start using or developing this extension controller locally

View File

@@ -6,13 +6,16 @@ gardener-extension-shoot-fleet-agent
---
apiVersion: shoot-fleet-agent-service.extensions.config.gardener.cloud/v1alpha1
kind: FleetAgentConfig
clientConnection:
defaultConfig:
kubeconfig: {{ .Values.fleetManager.kubeconfig }}
{{- if .Values.fleetManager.labels }}
labels: {{ .Values.fleetManager.labels | toYaml | nindent 6 }}
labels: {{ .Values.fleetManager.labels | toYaml | nindent 4 }}
{{- end }}
{{- if .Values.fleetManager.namespace }}
namespace: {{ .Values.fleetManager.namespace }}
namespace: {{ .Values.fleetManager.namespace }}
{{- end }}
{{- if .Values.fleetManager.projectConfig }}
projectConfig: {{ .Values.fleetManager.projectConfig | toYaml | nindent 2 }}
{{- end }}
{{- end }}

View File

@@ -27,9 +27,20 @@ controllers:
concurrentSyncs: 1
fleetManager:
#default config values
kubeconfig: #base64encoded kubeconfig of fleet manager cluster comes here
labels: # optional fleet Cluster crd labels
namespace: clusters # namespace where Fleet clusters stores Cluster CRD objects
#project specific values
# projectConfig:
# myproject:
# kubeconfig: #base64encoded kubeconfig of fleet manager cluster for myproject comes here
# labels: # optional fleet Cluster crd labels for myproject
# namespace: clusters # namespace where Fleet clusters stores Cluster CRD objects for myproject
# myotherproject:
# kubeconfig: #base64encoded kubeconfig of fleet manager cluster for myotherproject comes here
# labels: # optional fleet Cluster crd labels for myotherproject
# namespace: clusters # namespace where Fleet clusters stores Cluster CRD objects for myotherproject
disableControllers: []

View File

@@ -22,9 +22,10 @@ apiVersion: core.gardener.cloud/v1beta1
kind: ControllerRegistration
...
values:
clientConnection:
kubeconfig: abcd
labels:
defaultConfig:
clientConnection:
kubeconfig: abcd
labels:
```
If the `shoot-fleet-agent` should be enabled for every shoot cluster in your Gardener managed environment, you need to globally enable it in the `ControllerRegistration`:

View File

@@ -15,10 +15,11 @@ spec:
providerConfig:
apiVersion: service.fleet-agent.extensions.gardener.cloud/v1alpha1
kind:
clientConnection:
kubeconfig: base64 encoded kubeconfig
labels:
env: test
defaultConfig:
clientConnection:
kubeconfig: base64 encoded kubeconfig
labels:
env: test
```
<style>

View File

@@ -1,5 +1,22 @@
apiVersion: shoot-fleet-agent-service.extensions.config.gardener.cloud/v1alpha1
kind: FleetAgentConfig
clientConnection:
defaultConfig:
kubeconfig: #base64 encoded kubeconfig of fleet cluster
namespace: clusters #namespace to register clusters in fleet manager cluster
namespace: clusters #namespace to register clusters in fleet manager cluster
labels:
allshootswillhavethislabel: somevalue
# example of project specific config:
#projectConfig:
# projectABC:
# kubeconfig: #base64 encoded kubeconfig of ABC fleet cluster
# namespace: nsABC #namespace to register clusters in fleet manager cluster
# labels:
# myProjectABClabel1: myvalue
# myProjectABClabel2: myvalue2
# projectDEF:
# kubeconfig: #base64 encoded kubeconfig of DEF fleet cluster
# namespace: nsDEF #namespace to register clusters in fleet manager cluster
# labels:
# myProjectDEFlabel1: myvalue
# myProjectDEFlabel2: myvalue2

View File

@@ -11,7 +11,7 @@ spec:
deployment:
type: helm
providerConfig:
chart: H4sIAAAAAAAAA+0ca3PbNjKf+StwynWadELqYVludZObU2U19TR+jOW607m5yUAkJCEhCR5AylGT3m+/xYMUSb1ln91cuZOJJRBYLHaxL2CpCeYeCQm3yceYhIKy0BZTxmJ77BMS23hCwrj+7H7QADg5PlZ/Acp/1efmUbvZOm51OrK92emcnDxDx/ecdydIRIw5Qs84LHpTv23Pv1CY7CJ/Z0r8gE5Cxskhc0gBd9rttfIHsRfl32o2jtrPUOOhF7sK/uTyf46ucBwTHgoUM6RljO6mJESjhPoeDScowu4H2AfCsZ6jmykVSCRRxHgMH2Bf+GjisxEKcOxOofcrxImPYzojMC6e5tpx6AGCkEzgKQvRi4iTMf1IPHRHod9fXjroMvTniIVqpCQJRYQjn4bEsZzT4bthDLQBij4LAkBw2x8ij3JhORMa19X/mnzLGf3G6+r/tGE6qcv/0q9iFtYXiEawviRCY+oTYX3jiLsI/h/hD/B/HMDn/0DXW8wpSwQ6Ox3AhBFn74kbWw71CK7rftBkOTPhMo/UraeW6u6wk/73p5jHzhwH/kFzbNP/FviGov43OmASKv1/BMARvSVcyr2LZk0LR1Huq9NwGrZHZpZHhMtpFKv2HvoR3AFy5aZAY8ZRPCXojdlHaCh3D/pB7h7Uk7sHZTvLsUIckC7aZc9ZsxVkPDWz/g9hJ/33mOtM2MFzbNH/VqN5VIr/Tk46J5X+PwbU6+AGozl4ymmMXrgvEUjjOzTsXaHhAIFu41B9wWNwjxTHBLksiHA4d1APXL8aJsDlC8JnxHN0fCA9KYK/PnVhS4GHT0KPaDPRg2AC/gzZOL7DEGm81V1eoZmDWmApXBLFCAsUshjGMRjC76gAbKEa/vasP7gAwuQMVr0O/1IMKybJcBuLhlpOA72QHWrmUe3l3ySKOUsgTpnLSVECk8XZIgxBMLtcNjAgdImOV+LFBI7E8avBwUYxhu4YBkTwbZzviHBsiFYwjeOoW6/f3d05WFHsMD6pG6aJulmrDVSbUT+HEKFIbv87oRxWPJojsNcwAI+AVh/fKYFNOIFnMpgL0R2HoEgGX8IwXKLxqIg5HSVxgWkpjbD0fAdgG2yBWm+IzoY19H1veDZ8JZH8cnbz4+XPN+iX3vV17+LmbDBEl9eof3lxenZzdnkB335AvYtf0U9nF6evEKFSksBOCPpgBUAmleyEHSNxDQkpkJD6FBERl46pC0sLJwmYIjRh4BZCFZQSHlAhxSpUZAlofBrQWAWXYnldjgVdJqw7kcZO7mPHqcO/KcR+9bTNdlkYc+b7YA45mUguKHSOmKIN5hE5Btnt4HoIazffyEcMayT1dUhlOIUGKdrusgeUa7rSsbdxtiSUkhYovw4TjCummUbJH7l0l3EOYSpaUIAKFFhRHnvlXf+MsJP/jwnsZNhs4rCToL3PfyD+Pzmuzn8eA/aU/zvI+MH0CieOds8Ft8V/zZNy/nfUalXnP48Cnz7ZyCNjGkJUJLOzGrJ//93aKUOTQ0noqQFWHo96DE5nTCcanW3bVj7RXMJly/gRHLWTzSccjcBJSXFcnyVefdbEfjTFTesDDb2uzjNVmtlX3S0Xogr1JQTPJyezEPqQjIjG1kWfPiHnFvsJEY6a/xyHQAF3Fn0QECxXQ8ere/p4RHwhe8kgTn9bj9f0/gwB2a/S4X9GEL54MmropBNJHm6ZU0pGgLcm6bRZw/qZC2NK85iP6nMmNhrAOC0whAw1Uyyu1Dkdqokpbh13urVsNtXfifEEZSMiTsN4jGpfiX98Jco9OYmYoDHj800ogFtkFcLuwQhXLztdNczAIEqeuz4Wwhw6aCYYFggSQHNfpj2QsNT+/ho1nWbbbgA1fYjbR5AXxRSm/gl2kNnhzhsap0mHxCQguPcSH+Iy58O3QCSDbWxli103R/Pec4xIjHMTretmNCqvz2t12ycYImvia+2inmbVBjNh6xF2OiSP+qmNXwX7+n9tIgMc2UrTZiBTxm2ZlclUk6w+I956/9Mp+f8j6N+s/P9jQMnrKKneKqlepkKVJrN0TKydr3a55ziyAjA0Ho6x9Lb6jBe8Eg1dP/GyuMIBPKt3jbXkz67BWmBI2i+Kfs84W+UBcRQpp81DEhNlyDZNvGYIDUH64apZ5Zh0RYpo8a64y7vos5VzvSsZ9xkZX98ueqCnFnoO9tR/j0Q+mwfQuMd10Bb9Pz4+OSrH/yfHR5X+PwaUQ3PQEVHPNPw0E/cKFd8pSXhI1d5xQoRkuYIjpnV1rrXHuH0NhDyglCRzMqMS7Y9UyGj0rTyI7KKGeqLOZ4sJgmnsswRMg1q9UNER43r96s78bY4hD8CS/ReHUKr2hqrcBlD4wpCZ49a0CSGILt0PIgnqgricpGSY7M7OJWGZjS4kiw6YTJ1nAI7UbEvY0U0tkbGIVxYMWumDCkS9UGkH+qtzYzjgfA+cuZL1DLWdQqDay81LMYmIbvALkn4QWR8ibYTS7SwhTYv6Mi262Hd+I/Ce68o9vvdweWCNId3gGVfs/WyOBiWf4m4zOa6TF4hqu0p8/4qBWs4LqqrzySh7WNhkLAgwWMmswUb1veizkW1U4nWdxG69oCxmn6ntVBgR4I9ylJtwLtMrLo8tXFm78jpH9+LIX302nYfz0BX5JUh8U4L9eKo0Zn/cucHb5vGokLcXuUuWAlbzuL94Cgr0ntEQ1V7Vyrh0IY/NIqKvMuyFMVpHqR5ymY7oZQPKuEv5qk291/kdtJwAFzYTCWf5DaF37dtB73Rw/W7wdtCXl2PvLnrng+FVrz/IeiI0kyT/wFnQzTUiNKbE967JuNhq2qVF6maGeXHic6jZTOk9O++9GdwCsZfX7y5vB9e/XJ/dLNHaRdq/5gLj+spIeb3lWyKQE8ES7pLC5skauzLgNudoyyM+o5jTYBFzNxsbrS6sgvlJQM6lhRLLMlvluXIsCOQwzf9l3c3147BdZF1bF6hL7i2YLU5sDX1LYtqNvgK7NLOW7PFGLukYIL9zdctFaS3rj4MLCPfi2b4cc9NcNk/u2oxyQyabgkfGOPHjc+YBinarkVuEYexTh/4K9sz/dGvONe0yx7bzn6NGs5T/tZvN4yr/ewxYebAzVGq6IuXbS2d3SfxS9LkdtSU9GHXaJHRTa/+HOkv5EmFP/S/cluxqALbqf6d8/99uV/V/jwN5/c/r3eprMRXqahtxlU8QDz0dMoFkM6sDseTLBNg/1c7TBCWF6uNaOjFSpC0XIGfzrbhndmpPze8/Guyp/3yEXdPBJXxh9Ddagm3632mU3//ptCr//zhQPv+VAnZwEk9Bx37TZYKLK2tz7eMDzwi/Zj7ZFCKIUulGd/ORyIMeAB9y+rU8JlCVFJ49mhdHDfWmlwN54sukyIbR9A1nSaRWYKNazSokrqpNZz9CPgKLOkqbv6k9YSpwgP7v/SLQFv0/OlnS/1b7pHr/51HgwfV/Rx39Iu971mn7Wpu3bARczTxRtAETEqu/PhX6w528ArrXRIuupa91WGGc7EaA/BRln5IIRE12M3ZZ8nfgSuFrbrF6C67gJjCTBWmjqlGisVnziknB/GJ1SJOtZbHAJQrWasJaoXLmE1FuGIHO0HCi2xc9So/2JFZ+8mBz7iqNWnZppbxP0RfBNzIDlVg8Uu4t/Roxr/QE62udVY5smRp5obyKokUlQRnPfRngMsaBr5tFphS7xHkz4T0Rpu3qnEM/2+n+IEdIbrkpM4ya3Mtaf6/325/NaMPKzQVKKtcNjINey15uLzaJZCRfDld+Ij1Oy9+G7sv0XY7RDvf/e8Z/RQuwYyS4Lf9rn7TL5z+dRlX/8yhQtii5M+DCpq3Kf5Yty1PL7iFgT/2fRXj/34HYov/N9lG5/q91dNyo9P8xoHSpKuWr3zL1SlW/NfCWTLh4+Q2DVs2YDOgbU+hxxbye6Uz4gZbDBkp2tB5p2dKKpaSxWL54p9imTU5WcKQaaf6eO3ukb62//ubr7JI3oGHP99kdydUAAa4oUcRmr2nX1lPkLFA4ME6+fJ0Oq21YSHlYrlJA1ukFjM8PIkEPPYQKM7L80g1CoFwQwmYFLKtKTWX7Urnp4vp9R/OtY+a8UHWLvoDPFQXJheQ7O4t+f9gq7f8d7GT/Z5pzh/4A0Db732ku//5Xpzr/exTQNZLKLKYv03XRezzDAXanfNd6xhhPukhFCPJblKul7Pl3eC4sq5AtS+sCXbWVVfaydtwI5DFAZr1qnfY5lS3qVx029my2vpVdLVBs2c24r6yg6fkKi/98yXo/X9juZqMRZC3pLGqSrWamJv0ekJIrPDTVDfnKSMAGjWsLErtojH0hSc9VV2Z+qozIyr/0WX7b9fkIvKUqmADyvNwj+cskaiDSlxw8PbKSVa1EwMycLMJy4AVT16/YN6P6aW/umU5FZ50ec8LIxXuodxKr+WmorIOsmIcJU4T961PEdAJtWcs1oV30z39Z1nO0qvhLvpEjhaaLELvqc7FOTa9V+RctXb0vrnNbf0LjaTJygAvZ3q+vGZzXGJI4E5fLmCjTGPMjcYuSqfRXQAzHDRalOrWG03K+e8p7oAoqqKCCCiqooIIKKqigggoqqKCCCiqooIIKKqigggoqqKCCCiqooIIKKqjgy4P/ApkT0c4AeAAA
chart: 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
values:
image:
tag: v1.0.0-dev

View File

@@ -44,15 +44,70 @@ string
</tr>
<tr>
<td>
<code>clientConnection</code></br>
<code>defaultConfig</code></br>
<em>
k8s.io/component-base/config/v1alpha1.ClientConnectionConfiguration
<a href="#shoot-fleet-agent-service.extensions.config.gardener.cloud/v1alpha1.ProjectConfig">
ProjectConfig
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>ClientConnection specifies the kubeconfig file and client connection
settings for the proxy server to use when communicating with the apiserver.</p>
<p>DefaultConfiguration holds default config applied if no project config found</p>
</td>
</tr>
<tr>
<td>
<code>projectConfig</code></br>
<em>
<a href="#shoot-fleet-agent-service.extensions.config.gardener.cloud/v1alpha1.ProjectConfig">
map[string]github.com/javamachr/gardener-extension-shoot-fleet-agent/pkg/apis/config/v1alpha1.ProjectConfig
</a>
</em>
</td>
<td>
<p>ProjectConfiguration holds configuration overrides for each project</p>
</td>
</tr>
<tr>
<td>
<code>healthCheckConfig</code></br>
<em>
<a href="https://github.com/gardener/gardener/extensions/pkg/controller/healthcheck/config">
github.com/gardener/gardener/extensions/pkg/controller/healthcheck/config.HealthCheckConfig
</a>
</em>
</td>
<td>
</td>
</tr>
</tbody>
</table>
<h3 id="shoot-fleet-agent-service.extensions.config.gardener.cloud/v1alpha1.ProjectConfig">ProjectConfig
</h3>
<p>
(<em>Appears on:</em>
<a href="#shoot-fleet-agent-service.extensions.config.gardener.cloud/v1alpha1.FleetAgentConfig">FleetAgentConfig</a>)
</p>
<p>
<p>ProjectConfig holds configuration for single project</p>
</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>kubeconfig</code></br>
<em>
string
</em>
</td>
<td>
<p>Kubeconfig contains base64 encoded kubeconfig</p>
</td>
</tr>
<tr>
@@ -77,18 +132,6 @@ string
<p>namespace to store clusters registrations in Fleet managers cluster</p>
</td>
</tr>
<tr>
<td>
<code>healthCheckConfig</code></br>
<em>
<a href="https://github.com/gardener/gardener/extensions/pkg/controller/healthcheck/config">
github.com/gardener/gardener/extensions/pkg/controller/healthcheck/config.HealthCheckConfig
</a>
</em>
</td>
<td>
</td>
</tr>
</tbody>
</table>
<hr/>

View File

@@ -3,7 +3,6 @@ package config
import (
healthcheckconfig "github.com/gardener/gardener/extensions/pkg/controller/healthcheck/config"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
componentbaseconfig "k8s.io/component-base/config"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@@ -12,15 +11,23 @@ import (
type FleetAgentConfig struct {
metav1.TypeMeta
// ClientConnection specifies the kubeconfig file and client connection
// settings for the proxy server to use when communicating with the apiserver.
ClientConnection *componentbaseconfig.ClientConnectionConfiguration
// DefaultConfiguration holds default config applied if no project config found
DefaultConfiguration ProjectConfig
// ProjectConfiguration holds configuration overrides for each project
ProjectConfiguration map[string]ProjectConfig
HealthCheckConfig *healthcheckconfig.HealthCheckConfig
}
// ProjectConfig holds configuration for single project
type ProjectConfig struct {
// Kubeconfig contains base64 encoded kubeconfig
Kubeconfig string
// labels to use in Fleet Cluster registration
Labels map[string]string
//namespace to store clusters registrations in Fleet managers cluster
Namespace string
HealthCheckConfig *healthcheckconfig.HealthCheckConfig
}

View File

@@ -3,7 +3,6 @@ package v1alpha1
import (
healthcheckconfig "github.com/gardener/gardener/extensions/pkg/controller/healthcheck/config"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1"
)
// +genclient
@@ -13,16 +12,23 @@ import (
type FleetAgentConfig struct {
metav1.TypeMeta `json:",inline"`
// ClientConnection specifies the kubeconfig file and client connection
// settings for the proxy server to use when communicating with the apiserver.
// +optional
ClientConnection *componentbaseconfigv1alpha1.ClientConnectionConfiguration `json:"clientConnection,omitempty"`
// DefaultConfiguration holds default config applied if no project config found
DefaultConfiguration ProjectConfig `json:"defaultConfig,omitempty"`
// ProjectConfiguration holds configuration overrides for each project
ProjectConfiguration map[string]ProjectConfig `json:"projectConfig,omitempty"`
HealthCheckConfig *healthcheckconfig.HealthCheckConfig `json:"healthCheckConfig,omitempty"`
}
// ProjectConfig holds configuration for single project
type ProjectConfig struct {
// Kubeconfig contains base64 encoded kubeconfig
Kubeconfig string `json:"kubeconfig,omitempty"`
// labels to use in Fleet Cluster registration
Labels map[string]string `json:"labels,omitempty"`
//namespace to store clusters registrations in Fleet managers cluster
Namespace string `json:"namespace,omitempty"`
HealthCheckConfig *healthcheckconfig.HealthCheckConfig `json:"healthCheckConfig,omitempty"`
}

View File

@@ -27,8 +27,6 @@ import (
config "github.com/javamachr/gardener-extension-shoot-fleet-agent/pkg/apis/config"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
componentbaseconfig "k8s.io/component-base/config"
configv1alpha1 "k8s.io/component-base/config/v1alpha1"
)
func init() {
@@ -48,13 +46,24 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ProjectConfig)(nil), (*config.ProjectConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ProjectConfig_To_config_ProjectConfig(a.(*ProjectConfig), b.(*config.ProjectConfig), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*config.ProjectConfig)(nil), (*ProjectConfig)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_config_ProjectConfig_To_v1alpha1_ProjectConfig(a.(*config.ProjectConfig), b.(*ProjectConfig), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1alpha1_FleetAgentConfig_To_config_FleetAgentConfig(in *FleetAgentConfig, out *config.FleetAgentConfig, s conversion.Scope) error {
out.ClientConnection = (*componentbaseconfig.ClientConnectionConfiguration)(unsafe.Pointer(in.ClientConnection))
out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels))
out.Namespace = in.Namespace
if err := Convert_v1alpha1_ProjectConfig_To_config_ProjectConfig(&in.DefaultConfiguration, &out.DefaultConfiguration, s); err != nil {
return err
}
out.ProjectConfiguration = *(*map[string]config.ProjectConfig)(unsafe.Pointer(&in.ProjectConfiguration))
out.HealthCheckConfig = (*healthcheckconfig.HealthCheckConfig)(unsafe.Pointer(in.HealthCheckConfig))
return nil
}
@@ -65,9 +74,10 @@ func Convert_v1alpha1_FleetAgentConfig_To_config_FleetAgentConfig(in *FleetAgent
}
func autoConvert_config_FleetAgentConfig_To_v1alpha1_FleetAgentConfig(in *config.FleetAgentConfig, out *FleetAgentConfig, s conversion.Scope) error {
out.ClientConnection = (*configv1alpha1.ClientConnectionConfiguration)(unsafe.Pointer(in.ClientConnection))
out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels))
out.Namespace = in.Namespace
if err := Convert_config_ProjectConfig_To_v1alpha1_ProjectConfig(&in.DefaultConfiguration, &out.DefaultConfiguration, s); err != nil {
return err
}
out.ProjectConfiguration = *(*map[string]ProjectConfig)(unsafe.Pointer(&in.ProjectConfiguration))
out.HealthCheckConfig = (*healthcheckconfig.HealthCheckConfig)(unsafe.Pointer(in.HealthCheckConfig))
return nil
}
@@ -76,3 +86,27 @@ func autoConvert_config_FleetAgentConfig_To_v1alpha1_FleetAgentConfig(in *config
func Convert_config_FleetAgentConfig_To_v1alpha1_FleetAgentConfig(in *config.FleetAgentConfig, out *FleetAgentConfig, s conversion.Scope) error {
return autoConvert_config_FleetAgentConfig_To_v1alpha1_FleetAgentConfig(in, out, s)
}
func autoConvert_v1alpha1_ProjectConfig_To_config_ProjectConfig(in *ProjectConfig, out *config.ProjectConfig, s conversion.Scope) error {
out.Kubeconfig = in.Kubeconfig
out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels))
out.Namespace = in.Namespace
return nil
}
// Convert_v1alpha1_ProjectConfig_To_config_ProjectConfig is an autogenerated conversion function.
func Convert_v1alpha1_ProjectConfig_To_config_ProjectConfig(in *ProjectConfig, out *config.ProjectConfig, s conversion.Scope) error {
return autoConvert_v1alpha1_ProjectConfig_To_config_ProjectConfig(in, out, s)
}
func autoConvert_config_ProjectConfig_To_v1alpha1_ProjectConfig(in *config.ProjectConfig, out *ProjectConfig, s conversion.Scope) error {
out.Kubeconfig = in.Kubeconfig
out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels))
out.Namespace = in.Namespace
return nil
}
// Convert_config_ProjectConfig_To_v1alpha1_ProjectConfig is an autogenerated conversion function.
func Convert_config_ProjectConfig_To_v1alpha1_ProjectConfig(in *config.ProjectConfig, out *ProjectConfig, s conversion.Scope) error {
return autoConvert_config_ProjectConfig_To_v1alpha1_ProjectConfig(in, out, s)
}

View File

@@ -23,23 +23,18 @@ package v1alpha1
import (
config "github.com/gardener/gardener/extensions/pkg/controller/healthcheck/config"
runtime "k8s.io/apimachinery/pkg/runtime"
configv1alpha1 "k8s.io/component-base/config/v1alpha1"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FleetAgentConfig) DeepCopyInto(out *FleetAgentConfig) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.ClientConnection != nil {
in, out := &in.ClientConnection, &out.ClientConnection
*out = new(configv1alpha1.ClientConnectionConfiguration)
**out = **in
}
if in.Labels != nil {
in, out := &in.Labels, &out.Labels
*out = make(map[string]string, len(*in))
in.DefaultConfiguration.DeepCopyInto(&out.DefaultConfiguration)
if in.ProjectConfiguration != nil {
in, out := &in.ProjectConfiguration, &out.ProjectConfiguration
*out = make(map[string]ProjectConfig, len(*in))
for key, val := range *in {
(*out)[key] = val
(*out)[key] = *val.DeepCopy()
}
}
if in.HealthCheckConfig != nil {
@@ -67,3 +62,26 @@ func (in *FleetAgentConfig) DeepCopyObject() runtime.Object {
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ProjectConfig) DeepCopyInto(out *ProjectConfig) {
*out = *in
if in.Labels != nil {
in, out := &in.Labels, &out.Labels
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectConfig.
func (in *ProjectConfig) DeepCopy() *ProjectConfig {
if in == nil {
return nil
}
out := new(ProjectConfig)
in.DeepCopyInto(out)
return out
}

View File

@@ -23,23 +23,18 @@ package config
import (
healthcheckconfig "github.com/gardener/gardener/extensions/pkg/controller/healthcheck/config"
runtime "k8s.io/apimachinery/pkg/runtime"
componentbaseconfig "k8s.io/component-base/config"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FleetAgentConfig) DeepCopyInto(out *FleetAgentConfig) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.ClientConnection != nil {
in, out := &in.ClientConnection, &out.ClientConnection
*out = new(componentbaseconfig.ClientConnectionConfiguration)
**out = **in
}
if in.Labels != nil {
in, out := &in.Labels, &out.Labels
*out = make(map[string]string, len(*in))
in.DefaultConfiguration.DeepCopyInto(&out.DefaultConfiguration)
if in.ProjectConfiguration != nil {
in, out := &in.ProjectConfiguration, &out.ProjectConfiguration
*out = make(map[string]ProjectConfig, len(*in))
for key, val := range *in {
(*out)[key] = val
(*out)[key] = *val.DeepCopy()
}
}
if in.HealthCheckConfig != nil {
@@ -67,3 +62,26 @@ func (in *FleetAgentConfig) DeepCopyObject() runtime.Object {
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ProjectConfig) DeepCopyInto(out *ProjectConfig) {
*out = *in
if in.Labels != nil {
in, out := &in.Labels, &out.Labels
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectConfig.
func (in *ProjectConfig) DeepCopy() *ProjectConfig {
if in == nil {
return nil
}
out := new(ProjectConfig)
in.DeepCopyInto(out)
return out
}

View File

@@ -16,20 +16,21 @@ package controller
import (
"context"
b64 "encoding/base64"
"fmt"
"reflect"
"strings"
projConfig "github.com/javamachr/gardener-extension-shoot-fleet-agent/pkg/apis/config"
"github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/extensions"
"github.com/go-logr/logr"
fleetv1alpha1 "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/retry"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
@@ -51,42 +52,42 @@ const KubeconfigSecretName = "kubecfg"
// KubeconfigKey key in KubeconfigSecretName secret that holds kubeconfig for Shoot
const KubeconfigKey = "kubeconfig"
// DefaultConfigKey is the name of default config key.
const DefaultConfigKey = "default"
// NewActuator returns an actuator responsible for Extension resources.
func NewActuator(config config.Config) extension.Actuator {
fleetKubeConfig, _ := b64.StdEncoding.DecodeString(config.FleetAgentConfig.ClientConnection.Kubeconfig)
var kubeconfigPath string
var err error
if kubeconfigPath, err = writeKubeconfigToTempFile(fleetKubeConfig); err != nil {
panic(err)
}
fleetClientConfig, _ := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
var fleetNamespace = "clusters"
if len(config.Namespace) != 0 {
fleetNamespace = config.Namespace
}
fleetManager, err := NewManagerForConfig(fleetClientConfig, fleetNamespace)
if err != nil {
panic(err)
}
logger := log.Log.WithName(ActuatorName)
fleetManagers := initializeFleetManagers(config, logger)
return &actuator{
logger: log.Log.WithName(ActuatorName),
logger: logger,
serviceConfig: config,
fleetManager: fleetManager,
fleetManagers: fleetManagers,
}
}
type actuator struct {
client client.Client
config *rest.Config
decoder runtime.Decoder
fleetManager *FleetManager
client client.Client
config *rest.Config
decoder runtime.Decoder
fleetManagers map[string]*FleetManager
serviceConfig config.Config
logger logr.Logger
}
// initializeFleetManagers initializes fleet managers for given config
func initializeFleetManagers(config config.Config, logger logr.Logger) map[string]*FleetManager {
fleetManagers := make(map[string]*FleetManager)
fleetManagers[DefaultConfigKey] = createFleetManager(config.DefaultConfiguration, logger)
for name, projConfig := range config.ProjectConfiguration {
fleetManagers[name] = createFleetManager(projConfig, logger)
}
return fleetManagers
}
// Reconcile the Extension resource.
func (a *actuator) Reconcile(ctx context.Context, ex *extensionsv1alpha1.Extension) error {
namespace := ex.GetNamespace()
@@ -95,6 +96,9 @@ func (a *actuator) Reconcile(ctx context.Context, ex *extensionsv1alpha1.Extensi
if err != nil {
return err
}
if isShootedSeedCluster(cluster) {
return a.updateStatus(ctx, ex)
}
shootsConfigOverride := &config.Config{}
if ex.Spec.ProviderConfig != nil { //parse providerConfig defaults override for this Shoot
if _, _, err := a.decoder.Decode(ex.Spec.ProviderConfig.Raw, nil, shootsConfigOverride); err != nil {
@@ -112,12 +116,15 @@ func (a *actuator) Delete(ctx context.Context, ex *extensionsv1alpha1.Extension)
if err != nil {
return err
}
if isShootedSeedCluster(cluster) {
return nil
}
a.logger.Info("Component is being deleted", "component", "fleet-agent-management", "namespace", namespace, "cluster", buildCrdName(cluster))
err = a.fleetManager.DeleteKubeconfigSecret(ctx, buildCrdName(cluster))
err = a.getFleetManager(cluster).DeleteKubeconfigSecret(ctx, buildCrdName(cluster))
if err != nil {
a.logger.Error(err, "Failed to delete kubeconfig secret for Shoot cluster.", "cluster", buildCrdName(cluster))
}
err = a.fleetManager.DeleteCluster(ctx, buildCrdName(cluster))
err = a.getFleetManager(cluster).DeleteCluster(ctx, buildCrdName(cluster))
if err != nil {
a.logger.Error(err, "Failed to delete Cluster registration for Shoot cluster.", "cluster", buildCrdName(cluster))
}
@@ -157,23 +164,26 @@ func (a *actuator) InjectScheme(scheme *runtime.Scheme) error {
// ReconcileClusterInFleetManager reconciles cluster registration in remote fleet manager
func (a *actuator) ReconcileClusterInFleetManager(ctx context.Context, namespace string, cluster *extensions.Cluster, override *config.Config) {
a.logger.Info("Starting with already registered check")
labels := prepareLabels(cluster, a.serviceConfig, override)
registered, err := a.fleetManager.GetCluster(ctx, cluster.Shoot.Name)
if !errors.IsNotFound(err) {
labels := prepareLabels(cluster, getProjectConfig(cluster, &a.serviceConfig), getProjectConfig(cluster, override))
registered, err := a.getFleetManager(cluster).GetCluster(ctx, cluster.Shoot.Name)
if err != nil {
a.logger.Error(err, "Failed to get cluster registration for Shoot", "shoot", cluster.Shoot.Name)
}
if err == nil && registered != nil {
if reflect.DeepEqual(registered.Labels, labels) {
a.logger.Info("Cluster already registered - skipping registration", "clientId", registered.Spec.ClientID)
} else {
a.logger.Info("Updating labels of already registered cluster.", "clientId", registered.Spec.ClientID)
a.updateClusterLabelsInFleet(ctx, registered, labels)
a.updateClusterLabelsInFleet(ctx, registered, cluster, labels)
}
return
}
a.registerNewClusterInFleet(ctx, namespace, cluster, labels)
}
func (a *actuator) updateClusterLabelsInFleet(ctx context.Context, clusterRegistration *fleetv1alpha1.Cluster, labels map[string]string) {
func (a *actuator) updateClusterLabelsInFleet(ctx context.Context, clusterRegistration *fleetv1alpha1.Cluster, cluster *extensions.Cluster, labels map[string]string) {
clusterRegistration.Labels = labels
_, err := a.fleetManager.UpdateCluster(ctx, clusterRegistration)
_, err := a.getFleetManager(cluster).UpdateCluster(ctx, clusterRegistration)
if err != nil {
a.logger.Error(err, "Failed to update cluster labels in Fleet registration.", "clusterName", clusterRegistration.Name)
}
@@ -207,10 +217,10 @@ func (a *actuator) registerNewClusterInFleet(ctx context.Context, namespace stri
KubeConfigSecret: "kubecfg-" + buildCrdName(cluster),
},
}
if _, err = a.fleetManager.CreateKubeconfigSecret(ctx, &kubeconfigSecret); err != nil {
if _, err = a.getFleetManager(cluster).CreateKubeconfigSecret(ctx, &kubeconfigSecret); err != nil {
a.logger.Error(err, "Failed to create secret with kubeconfig for Fleet registration")
}
if _, err = a.fleetManager.CreateCluster(ctx, &clusterRegistration); err != nil {
if _, err = a.getFleetManager(cluster).CreateCluster(ctx, &clusterRegistration); err != nil {
a.logger.Error(err, "Failed to create Cluster for Fleet registration")
}
a.logger.Info("Registered shoot cluster in Fleet Manager ", "registration", clusterRegistration)
@@ -219,17 +229,18 @@ func (a *actuator) registerNewClusterInFleet(ctx context.Context, namespace stri
}
}
func prepareLabels(cluster *extensions.Cluster, serviceConfig config.Config, override *config.Config) map[string]string {
func prepareLabels(cluster *extensions.Cluster, serviceConfig projConfig.ProjectConfig, override projConfig.ProjectConfig) map[string]string {
labels := make(map[string]string)
labels["corebundle"] = "true"
labels["region"] = cluster.Shoot.Spec.Region
labels["cluster"] = cluster.Shoot.Name
labels["seed"] = cluster.Seed.Name
if len(override.Labels) > 0 { //adds labels from Shoot configuration
for key, value := range override.Labels {
labels[key] = value
}
} else {
if len(serviceConfig.FleetAgentConfig.Labels) > 0 { //adds labels from default configuration
if len(serviceConfig.Labels) > 0 { //adds labels from default configuration
for key, value := range serviceConfig.Labels {
labels[key] = value
}
@@ -238,13 +249,41 @@ func prepareLabels(cluster *extensions.Cluster, serviceConfig config.Config, ove
return labels
}
// buildCrdName creates a unique name for cluster registration resources in Fleet manager cluster
func buildCrdName(cluster *extensions.Cluster) string {
return cluster.Seed.Name + "" + cluster.Shoot.Name
}
func (a *actuator) updateStatus(ctx context.Context, ex *extensionsv1alpha1.Extension) error {
return controller.TryUpdateStatus(ctx, retry.DefaultBackoff, a.client, ex, func() error {
return nil
})
}
func (a *actuator) getFleetManager(cluster *extensions.Cluster) *FleetManager {
manager, present := a.fleetManagers[getProjectName(cluster)]
if !present {
return a.fleetManagers[DefaultConfigKey]
}
return manager
}
// getProjectConfig return project specific or default config
func getProjectConfig(cluster *extensions.Cluster, serviceConfig *config.Config) projConfig.ProjectConfig {
name := getProjectName(cluster)
projectConfig, present := serviceConfig.ProjectConfiguration[name]
if !present {
return serviceConfig.DefaultConfiguration
}
return projectConfig
}
// buildCrdName creates a unique name for cluster registration resources in Fleet manager cluster
func buildCrdName(cluster *extensions.Cluster) string {
return cluster.Seed.Name + "" + cluster.Shoot.Name
}
// isShootedSeedCluster checks if clusters purpose is Infrastructure
func isShootedSeedCluster(cluster *extensions.Cluster) bool {
return *cluster.Shoot.Spec.Purpose == v1beta1.ShootPurposeInfrastructure
}
// getProjectName extracts project name from Shoots namespace
func getProjectName(cluster *extensions.Cluster) string {
return cluster.Shoot.Namespace[strings.LastIndex(cluster.Shoot.Namespace, "-")+1:]
}

View File

@@ -2,7 +2,13 @@ package controller
import (
"context"
b64 "encoding/base64"
"github.com/go-logr/logr"
"k8s.io/client-go/tools/clientcmd"
fleetConfig "github.com/javamachr/gardener-extension-shoot-fleet-agent/pkg/apis/config"
clientset "github.com/javamachr/gardener-extension-shoot-fleet-agent/pkg/client/fleet/clientset/versioned"
"github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
corev1 "k8s.io/api/core/v1"
@@ -66,3 +72,31 @@ func (f *FleetManager) CreateKubeconfigSecret(ctx context.Context, secret *corev
func (f *FleetManager) DeleteKubeconfigSecret(ctx context.Context, secretName string) error {
return f.secretClient.CoreV1().Secrets(f.namespace).Delete(ctx, secretName, metav1.DeleteOptions{})
}
// createFleetManager creates fleet manager for given configuration
func createFleetManager(config fleetConfig.ProjectConfig, logger logr.Logger) *FleetManager {
logger.Info("Creating Fleet manager for config", "config", config)
fleetKubeConfig, err := b64.StdEncoding.DecodeString(config.Kubeconfig)
if err != nil {
panic(err)
}
var kubeconfigPath string
if kubeconfigPath, err = writeKubeconfigToTempFile(fleetKubeConfig); err != nil {
panic(err)
}
logger.Info("Written kubeconfig to temp", "file", kubeconfigPath)
fleetClientConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
if err != nil {
panic(err)
}
logger.Info("Fleet k8s client successfully built.")
var fleetNamespace = "clusters"
if len(config.Namespace) != 0 {
fleetNamespace = config.Namespace
}
fleetManager, err := NewManagerForConfig(fleetClientConfig, fleetNamespace)
if err != nil {
panic(err)
}
return fleetManager
}