Skip to content

Commit

Permalink
Self targets (run-int-tests) (#1254)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertgraeff authored Nov 11, 2024
1 parent b8bcdc6 commit c6369bb
Show file tree
Hide file tree
Showing 53 changed files with 956 additions and 393 deletions.
16 changes: 14 additions & 2 deletions apis/core/v1alpha1/targettypes/kubernetes_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ type KubernetesClusterTargetConfig struct {
Kubeconfig ValueRef `json:"kubeconfig"`

OIDCConfig *OIDCConfig `json:"oidcConfig,omitempty"`

// SelfConfig contains the config for a Target that points to the landscaper resource cluster.
SelfConfig *SelfConfig `json:"selfConfig,omitempty"`
}

// DefaultKubeconfigKey is the default that is used to hold a kubeconfig.
Expand All @@ -37,6 +40,7 @@ type ValueRef struct {
type kubeconfigJSON struct {
Kubeconfig *ValueRef `json:"kubeconfig"`
OIDCConfig *OIDCConfig `json:"oidcConfig,omitempty"`
SelfConfig *SelfConfig `json:"selfConfig,omitempty"`
}

// MarshalJSON implements the json marshaling for a JSON
Expand All @@ -60,12 +64,15 @@ func (v *ValueRef) UnmarshalJSON(data []byte) error {
func (kc *KubernetesClusterTargetConfig) UnmarshalJSON(data []byte) error {
kj := &kubeconfigJSON{}
err := json.Unmarshal(data, kj)
if err == nil && (kj.Kubeconfig != nil || kj.OIDCConfig != nil) {
if err == nil && (kj.Kubeconfig != nil || kj.OIDCConfig != nil || kj.SelfConfig != nil) {
// parsing was successful
if kj.Kubeconfig != nil {
kc.Kubeconfig = *kj.Kubeconfig
}
kc.OIDCConfig = kj.OIDCConfig
if kj.OIDCConfig != nil {
kc.OIDCConfig = kj.OIDCConfig
}
kc.SelfConfig = kj.SelfConfig
return nil
}
return kc.Kubeconfig.UnmarshalJSON(data)
Expand All @@ -87,3 +94,8 @@ type OIDCConfig struct {
Audience []string `json:"audience,omitempty"`
ExpirationSeconds *int64 `json:"expirationSeconds,omitempty"`
}

type SelfConfig struct {
ServiceAccount v1.LocalObjectReference `json:"serviceAccount,omitempty"`
ExpirationSeconds *int64 `json:"expirationSeconds,omitempty"`
}
31 changes: 31 additions & 0 deletions apis/core/v1alpha1/targettypes/kubernetes_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,35 @@ var _ = Describe("Kubernetes Cluster Target Types", func() {
},
}))
})

It("should marshal a self config", func() {
targetConfig := &targettypes.KubernetesClusterTargetConfig{
SelfConfig: &targettypes.SelfConfig{
ServiceAccount: v1.LocalObjectReference{
Name: "test-account",
},
ExpirationSeconds: ptr.To[int64](300),
},
}
targetConfigJSON, err := json.Marshal(targetConfig)
Expect(err).NotTo(HaveOccurred())
Expect(targetConfigJSON).To(MatchJSON(`{"kubeconfig":null,"selfConfig":{"serviceAccount":{"name":"test-account"},"expirationSeconds":300}}`))
})

It("should unmarshal a self config", func() {
configJSON := []byte(`{"selfConfig":{"serviceAccount":{"name":"test-account"},"expirationSeconds":300}}`)
config := &targettypes.KubernetesClusterTargetConfig{}
Expect(json.Unmarshal(configJSON, config)).To(Succeed())
Expect(config).To(Equal(&targettypes.KubernetesClusterTargetConfig{
Kubeconfig: targettypes.ValueRef{
StrVal: nil,
},
SelfConfig: &targettypes.SelfConfig{
ServiceAccount: v1.LocalObjectReference{
Name: "test-account",
},
ExpirationSeconds: ptr.To[int64](300),
},
}))
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ If your target cluster is a Gardener shoot cluster, you typically have a
for the target cluster. It is **not** possible to use such a kubeconfig in a `Target` custom resource.
You have the following alternatives:

- Use an [OIDC Target](../../usage/Targets.md#oidc-target-to-kubernetes-target-cluster).
- Use an [OIDC Target](../../../usage/Targets.md#oidc-target-to-kubernetes-target-cluster)
- Use a Target whose kubeconfig is based on a ServiceAccount token, as described below.

## Targets Whose Kubeconfig is Based On a ServiceAccount Token
Expand Down
68 changes: 68 additions & 0 deletions docs/guided-tour/targets/02-self-targets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
title: Self Targets
sidebar_position: 2
---

# Self Targets

This example demonstrates how you can use the Landscaper to deploy objects on its own resource cluster.
This means in this example the resource cluster and the target cluster are the same.
For this use-case, the Landscaper provides a special type of targets, so-called
[Self Targets](../../../usage/Targets.md#targets-to-the-landscaper-resource-cluster-self-targets).
Their advantage is that you do not need to include a kubeconfig into them. Instead, the Target references a ServiceAccount
in the same Namespace. The Self Target in this example looks as follows:

```yaml
apiVersion: landscaper.gardener.cloud/v1alpha1
kind: Target
metadata:
name: self-target
namespace: cu-example
spec:
type: landscaper.gardener.cloud/kubernetes-cluster
config:
selfConfig:
serviceAccount:
name: self-serviceaccount
expirationSeconds: 3600
```
This Target references a [ServiceAccount `self-serviceaccount`](installation/serviceaccount.yaml.tpl).
A [ClusterRoleBinding `landscaper:guided-tour:self`](installation/clusterrolebinding.yaml.tpl) binds the ServiceAccount
to the ClusterRole `cluster-admin`, so that it has the necessary rights to create objects on the resource cluster.
The [Installation `self-inst`](installation/installation.yaml.tpl) uses the Target to deploy a ConfigMap on the
resource cluster.


## Procedure

1. In the [settings](commands/settings) file, adjust the variables `RESOURCE_CLUSTER_KUBECONFIG_PATH`.

2. On the Landscaper resource cluster, create namespaces `cu-example` and `example`.

3. Run script [commands/deploy-k8s-resources.sh](commands/deploy-k8s-resources.sh).
It templates the following objects and applies them to the resource cluster:
- [ServiceAccount `self-serviceaccount`](installation/serviceaccount.yaml.tpl),
- [ClusterRoleBinding `landscaper:guided-tour:self`](installation/clusterrolebinding.yaml.tpl),
- [Target `self-target`](installation/target.yaml.tpl),
- [Installation `self-inst`](installation/installation.yaml.tpl).

The diagram below provides an overview of these objects.

4. Wait until the Installation is in phase `Succeeded` and check that it has created a ConfigMap `self-target-example`
in namespace `example` on the resource cluster.

![diagram](./images/self-targets.png)


## Cleanup

You can remove the Installation with the
[delete-installation script](commands/delete-installation.sh).
When the Installation is gone, you can delete the Target, ClusterRoleBinding, and ServiceAccount with the
[delete-other-k8s-resources script](commands/delete-other-k8s-resources.sh).


## References

[Self Targets](../../../usage/Targets.md#targets-to-the-landscaper-resource-cluster-self-targets)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
#
# SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
#
# SPDX-License-Identifier: Apache-2.0

set -o errexit

COMPONENT_DIR="$(dirname $0)/.."
cd "${COMPONENT_DIR}"
COMPONENT_DIR="$(pwd)"
echo "COMPONENT_DIR: ${COMPONENT_DIR}"

source "${COMPONENT_DIR}/commands/settings"

echo "deleting installation"
kubectl delete installation "self-inst" -n "${NAMESPACE}" --kubeconfig="${RESOURCE_CLUSTER_KUBECONFIG_PATH}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash
#
# SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
#
# SPDX-License-Identifier: Apache-2.0

set -o errexit

COMPONENT_DIR="$(dirname $0)/.."
cd "${COMPONENT_DIR}"
COMPONENT_DIR="$(pwd)"
echo "COMPONENT_DIR: ${COMPONENT_DIR}"

source "${COMPONENT_DIR}/commands/settings"

echo "deleting target"
kubectl delete target "self-target" -n "${NAMESPACE}" --kubeconfig="${RESOURCE_CLUSTER_KUBECONFIG_PATH}"

echo "deleting clusterrolebinding"
kubectl delete clusterrolebinding "landscaper:guided-tour:self" --kubeconfig="${RESOURCE_CLUSTER_KUBECONFIG_PATH}"

echo "deleting serviceaccount"
kubectl delete serviceaccount "self-serviceaccount" -n "${NAMESPACE}" --kubeconfig="${RESOURCE_CLUSTER_KUBECONFIG_PATH}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash
#
# SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
#
# SPDX-License-Identifier: Apache-2.0

set -o errexit

COMPONENT_DIR="$(dirname $0)/.."
cd "${COMPONENT_DIR}"
COMPONENT_DIR="$(pwd)"
echo "COMPONENT_DIR: ${COMPONENT_DIR}"

source "${COMPONENT_DIR}/commands/settings"

TMP_DIR=`mktemp -d`
echo "TMP_DIR: ${TMP_DIR}"

echo "creating serviceaccount"
outputFile="${TMP_DIR}/serviceaccount.yaml"
export namespace="${NAMESPACE}"
inputFile="${COMPONENT_DIR}/installation/serviceaccount.yaml.tpl"
envsubst < ${inputFile} > ${outputFile}
kubectl apply -f ${outputFile} --kubeconfig="${RESOURCE_CLUSTER_KUBECONFIG_PATH}"

echo "creating clusterrolebinding"
outputFile="${TMP_DIR}/clusterrolebinding.yaml"
export namespace="${NAMESPACE}"
inputFile="${COMPONENT_DIR}/installation/clusterrolebinding.yaml.tpl"
envsubst < ${inputFile} > ${outputFile}
kubectl apply -f ${outputFile} --kubeconfig="${RESOURCE_CLUSTER_KUBECONFIG_PATH}"

echo "creating target"
outputFile="${TMP_DIR}/target.yaml"
export namespace="${NAMESPACE}"
inputFile="${COMPONENT_DIR}/installation/target.yaml.tpl"
envsubst < ${inputFile} > ${outputFile}
kubectl apply -f ${outputFile} --kubeconfig="${RESOURCE_CLUSTER_KUBECONFIG_PATH}"

echo "creating installation"
outputFile="${TMP_DIR}/installation.yaml"
export namespace="${NAMESPACE}"
inputFile="${COMPONENT_DIR}/installation/installation.yaml.tpl"
envsubst < ${inputFile} > ${outputFile}
kubectl apply -f ${outputFile} --kubeconfig="${RESOURCE_CLUSTER_KUBECONFIG_PATH}"
5 changes: 5 additions & 0 deletions docs/guided-tour/targets/02-self-targets/commands/settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# path to the kubeconfig of the resource cluster, i.e. the cluster on which installations, targets, etc. are created
RESOURCE_CLUSTER_KUBECONFIG_PATH="/Users/${USER}/tmp/kubes/kubeconfig.yaml"

# namespace for resources in the resource cluster
NAMESPACE="cu-example"
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: landscaper:guided-tour:self
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: self-serviceaccount
namespace: ${namespace}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
apiVersion: landscaper.gardener.cloud/v1alpha1
kind: Installation
metadata:
name: self-inst
namespace: ${namespace}
annotations:
landscaper.gardener.cloud/operation: reconcile

spec:

imports:
targets:
- name: cluster
target: self-target

blueprint:
inline:
filesystem:
blueprint.yaml: |
apiVersion: landscaper.gardener.cloud/v1alpha1
kind: Blueprint
jsonSchema: "https://json-schema.org/draft/2019-09/schema"

imports:
- name: cluster
type: target
targetType: landscaper.gardener.cloud/kubernetes-cluster

deployExecutions:
- name: default
type: GoTemplate
template: |
deployItems:
- name: default-deploy-item
type: landscaper.gardener.cloud/kubernetes-manifest

target:
import: cluster

config:
apiVersion: manifest.deployer.landscaper.gardener.cloud/v1alpha2
kind: ProviderConfiguration
updateStrategy: update
manifests:
- policy: manage
manifest:
apiVersion: v1
kind: ConfigMap
metadata:
name: self-target-example
namespace: example
data:
testData: hello
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: self-serviceaccount
namespace: ${namespace}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: landscaper.gardener.cloud/v1alpha1
kind: Target
metadata:
name: self-target
namespace: ${namespace}
spec:
type: landscaper.gardener.cloud/kubernetes-cluster
config:
selfConfig:
serviceAccount:
name: self-serviceaccount
expirationSeconds: 3600
Loading

0 comments on commit c6369bb

Please sign in to comment.