Skip to content

Commit

Permalink
feat(chart): create operator configuration resource via helm chart
Browse files Browse the repository at this point in the history
  • Loading branch information
basti1302 committed Sep 18, 2024
1 parent 8e30e46 commit 6930991
Show file tree
Hide file tree
Showing 39 changed files with 723 additions and 134 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ golangci-lint:
lint: golangci-lint ## Run golangci-lint linter & yamllint
@echo --------------------------------
$(GOLANGCI_LINT) run
helm lint helm-chart/dash0-operator --set operator.disableSecretCheck=true --set operator.disableOtlpEndpointCheck=true
helm lint helm-chart/dash0-operator

.PHONY: lint-fix
lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes
Expand Down
9 changes: 5 additions & 4 deletions api/dash0monitoring/v1alpha1/types_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ type Export struct {
type Dash0Configuration struct {
// The URL of the Dash0 ingress endpoint to which telemetry data will be sent. This property is mandatory. The value
// needs to be the OTLP/gRPC endpoint of your Dash0 organization. The correct OTLP/gRPC endpoint can be copied fom
// https://app.dash0.com/settings. The correct endpoint value will always start with `ingress.` and end in
// `dash0.com:4317`.
// https://app.dash0.com -> organization settings -> "Endpoints". The correct endpoint value will always start with
// `ingress.` and end in `dash0.com:4317`.
//
// +kubebuilder:validation:Required
Endpoint string `json:"endpoint"`
Expand All @@ -61,14 +61,15 @@ type Dash0Configuration struct {
type Authorization struct {
// The Dash0 authorization token. This property is optional, but either this property or the SecretRef property has
// to be provided. If both are provided, the token will be used and SecretRef will be ignored. The authorization
// token for your Dash0 organization can be copied from https://app.dash0.com/settings.
// token for your Dash0 organization can be copied from https://app.dash0.com -> organization settings ->
// "Auth Tokens".
//
// +kubebuilder:validation:Optional
Token *string `json:"token"` // either token or secret ref, with token taking precedence

// A reference to a Kubernetes secret containing the Dash0 authorization token. This property is optional, and is
// ignored if the token property is set. The authorization token for your Dash0 organization can be copied from
// https://app.dash0.com/settings.
// https://app.dash0.com -> organization settings -> "Auth Tokens".
//
// +kubebuilder:validation:Optional
SecretRef *SecretRef `json:"secretRef"`
Expand Down
85 changes: 72 additions & 13 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ import (
"github.com/dash0hq/dash0-operator/internal/backendconnection/otelcolresources"
"github.com/dash0hq/dash0-operator/internal/dash0/controller"
"github.com/dash0hq/dash0-operator/internal/dash0/instrumentation"
"github.com/dash0hq/dash0-operator/internal/dash0/removal"
"github.com/dash0hq/dash0-operator/internal/dash0/predelete"
"github.com/dash0hq/dash0-operator/internal/dash0/selfmonitoring"
"github.com/dash0hq/dash0-operator/internal/dash0/startup"
"github.com/dash0hq/dash0-operator/internal/dash0/util"
"github.com/dash0hq/dash0-operator/internal/dash0/webhooks"
//+kubebuilder:scaffold:imports
Expand Down Expand Up @@ -105,25 +106,40 @@ func init() {

func main() {
ctx := context.Background()
var uninstrumentAll bool
var operatorConfigurationEndpoint string
var operatorConfigurationToken string
var operatorConfigurationSecretRefName string
var operatorConfigurationSecretRefKey string
var isUninstrumentAll bool
var metricsAddr string
var enableLeaderElection bool
var probeAddr string
var secureMetrics bool
var enableHTTP2 bool
flag.BoolVar(&uninstrumentAll, "uninstrument-all", false,
"If set, the process will remove all Dash0 monitoring resources from all namespaces in the cluster. This "+
"will trigger the Dash0 monitoring resources' finalizers in each namespace, which in turn will revert the "+
"instrumentation of all workloads in all namespaces.")

flag.BoolVar(&isUninstrumentAll, "uninstrument-all", false,
"If set, the process will remove all Dash0 monitoring resources from all namespaces in the cluste, then "+
"exit. This will trigger the Dash0 monitoring resources' finalizers in each namespace, which in turn will "+
"revert the instrumentation of all workloads in all namespaces.")
flag.StringVar(&operatorConfigurationEndpoint, "operator-configuration-endpoint", "",
"The Dash0 endpoint gRPC URL for creating an operator configuration resource.")
flag.StringVar(&operatorConfigurationToken, "operator-configuration-token", "",
"The Dash0 auth token for creating an operator configuration resource.")
flag.StringVar(&operatorConfigurationSecretRefName, "operator-configuration-secret-ref-name", "",
"The name of an existing Kubernetes secret containing the Dash0 auth token, used to creating an operator "+
"configuration resource.")
flag.StringVar(&operatorConfigurationSecretRefKey, "operator-configuration-secret-ref-key", "",
"The key in an existing Kubernetes secret containing the Dash0 auth token, used to creating an operator "+
"configuration resource.")
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.BoolVar(&secureMetrics, "metrics-secure", false,
"If set, the metrics endpoint is served securely")
"If set, the metrics endpoint is served securely.")
flag.BoolVar(&enableHTTP2, "enable-http2", false,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
"If set, HTTP/2 will be enabled for the metrics and webhook servers.")

var developmentMode bool
developmentModeRaw, isSet := os.LookupEnv(developmentModeEnvVarName)
Expand All @@ -143,8 +159,8 @@ func main() {

ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

if uninstrumentAll {
if err := deleteDash0MonitoringResourcesInAllNamespaces(&setupLog); err != nil {
if isUninstrumentAll {
if err := deleteMonitoringResourcesInAllNamespaces(&setupLog); err != nil {
setupLog.Error(err, "deleting the Dash0 monitoring resources in all namespaces failed")
os.Exit(1)
}
Expand Down Expand Up @@ -196,6 +212,18 @@ func main() {
map[string]string{semconv.AttributeK8SDeploymentUID: string(deploymentSelfReference.UID)},
)

var operatorConfiguration *startup.OperatorConfigurationValues
if len(operatorConfigurationEndpoint) > 0 {
operatorConfiguration = &startup.OperatorConfigurationValues{
Endpoint: operatorConfigurationEndpoint,
Token: operatorConfigurationToken,
SecretRef: startup.SecretRef{
Name: operatorConfigurationSecretRefName,
Key: operatorConfigurationSecretRefKey,
},
}
}

if err = startOperatorManager(
ctx,
metricsAddr,
Expand All @@ -204,6 +232,7 @@ func main() {
webhookServer,
probeAddr,
enableLeaderElection,
operatorConfiguration,
developmentMode,
); err != nil {
setupLog.Error(err, "The Dash0 operator manager process failed to start.")
Expand All @@ -219,6 +248,7 @@ func startOperatorManager(
webhookServer k8swebhook.Server,
probeAddr string,
enableLeaderElection bool,
operatorConfiguration *startup.OperatorConfigurationValues,
developmentMode bool,
) error {
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Expand Down Expand Up @@ -285,7 +315,7 @@ func startOperatorManager(
developmentMode,
)

err = startDash0Controllers(ctx, mgr, clientset, developmentMode)
err = startDash0Controllers(ctx, mgr, clientset, operatorConfiguration, developmentMode)
if err != nil {
return err
}
Expand Down Expand Up @@ -396,6 +426,7 @@ func startDash0Controllers(
ctx context.Context,
mgr manager.Manager,
clientset *kubernetes.Clientset,
operatorConfiguration *startup.OperatorConfigurationValues,
developmentMode bool,
) error {
oTelCollectorBaseUrl :=
Expand All @@ -419,8 +450,10 @@ func startDash0Controllers(
ctx,
clientset,
mgr.GetEventRecorderFor("dash0-startup-tasks"),
operatorConfiguration,
images,
oTelCollectorBaseUrl,
&setupLog,
)

logCurrentSelfMonitoringSettings(deploymentSelfReference)
Expand Down Expand Up @@ -555,9 +588,17 @@ func executeStartupTasks(
ctx context.Context,
clientset *kubernetes.Clientset,
eventRecorder record.EventRecorder,
operatorConfiguration *startup.OperatorConfigurationValues,
images util.Images,
oTelCollectorBaseUrl string,
logger *logr.Logger,
) {
createOperatorConfiguration(
ctx,
startupTasksK8sClient,
operatorConfiguration,
logger,
)
instrumentAtStartup(
ctx,
startupTasksK8sClient,
Expand Down Expand Up @@ -618,8 +659,26 @@ func logCurrentSelfMonitoringSettings(deploymentSelfReference *appsv1.Deployment
}
}

func deleteDash0MonitoringResourcesInAllNamespaces(logger *logr.Logger) error {
handler, err := removal.NewOperatorPreDeleteHandler()
func createOperatorConfiguration(
ctx context.Context,
k8sClient client.Client,
operatorConfiguration *startup.OperatorConfigurationValues,
logger *logr.Logger,
) {
if operatorConfiguration != nil {
handler := startup.AutoOperatorConfigurationResourceHandler{
Client: k8sClient,
OperatorNamespace: envVars.operatorNamespace,
NamePrefix: envVars.oTelCollectorNamePrefix,
}
if err := handler.CreateOperatorConfigurationResource(ctx, operatorConfiguration, logger); err != nil {
logger.Error(err, "Failed to create the requested Dash0 operator configuration resource.")
}
}
}

func deleteMonitoringResourcesInAllNamespaces(logger *logr.Logger) error {
handler, err := predelete.NewOperatorPreDeleteHandler()
if err != nil {
logger.Error(err, "Failed to create the OperatorPreDeleteHandler.")
return err
Expand Down
9 changes: 5 additions & 4 deletions config/crd/bases/operator.dash0.com_dash0monitorings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ spec:
description: |-
A reference to a Kubernetes secret containing the Dash0 authorization token. This property is optional, and is
ignored if the token property is set. The authorization token for your Dash0 organization can be copied from
https://app.dash0.com/settings.
https://app.dash0.com -> organization settings -> "Auth Tokens".
properties:
key:
default: token
Expand All @@ -89,7 +89,8 @@ spec:
description: |-
The Dash0 authorization token. This property is optional, but either this property or the SecretRef property has
to be provided. If both are provided, the token will be used and SecretRef will be ignored. The authorization
token for your Dash0 organization can be copied from https://app.dash0.com/settings.
token for your Dash0 organization can be copied from https://app.dash0.com -> organization settings ->
"Auth Tokens".
type: string
type: object
dataset:
Expand All @@ -102,8 +103,8 @@ spec:
description: |-
The URL of the Dash0 ingress endpoint to which telemetry data will be sent. This property is mandatory. The value
needs to be the OTLP/gRPC endpoint of your Dash0 organization. The correct OTLP/gRPC endpoint can be copied fom
https://app.dash0.com/settings. The correct endpoint value will always start with `ingress.` and end in
`dash0.com:4317`.
https://app.dash0.com -> organization settings -> "Endpoints". The correct endpoint value will always start with
`ingress.` and end in `dash0.com:4317`.
type: string
required:
- authorization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ spec:
description: |-
A reference to a Kubernetes secret containing the Dash0 authorization token. This property is optional, and is
ignored if the token property is set. The authorization token for your Dash0 organization can be copied from
https://app.dash0.com/settings.
https://app.dash0.com -> organization settings -> "Auth Tokens".
properties:
key:
default: token
Expand All @@ -89,7 +89,8 @@ spec:
description: |-
The Dash0 authorization token. This property is optional, but either this property or the SecretRef property has
to be provided. If both are provided, the token will be used and SecretRef will be ignored. The authorization
token for your Dash0 organization can be copied from https://app.dash0.com/settings.
token for your Dash0 organization can be copied from https://app.dash0.com -> organization settings ->
"Auth Tokens".
type: string
type: object
dataset:
Expand All @@ -102,8 +103,8 @@ spec:
description: |-
The URL of the Dash0 ingress endpoint to which telemetry data will be sent. This property is mandatory. The value
needs to be the OTLP/gRPC endpoint of your Dash0 organization. The correct OTLP/gRPC endpoint can be copied fom
https://app.dash0.com/settings. The correct endpoint value will always start with `ingress.` and end in
`dash0.com:4317`.
https://app.dash0.com -> organization settings -> "Endpoints". The correct endpoint value will always start with
`ingress.` and end in `dash0.com:4317`.
type: string
required:
- authorization
Expand Down
6 changes: 6 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ rules:
- patch
- update
- watch
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
- apiGroups:
- ""
resources:
Expand Down
3 changes: 2 additions & 1 deletion helm-chart/dash0-operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@ spec:
If you want to provide the Dash0 authorization token via a Kubernetes secret instead of providing the token as a string,
create the secret in the namespace where the Dash0 operator is installed.
If you followed the guide above, the name of that namespace is `dash0-system`.
The authorization token for your Dash0 organization can be copied from https://app.dash0.com -> organization settings -> "Auth Tokens".
The authorization token for your Dash0 organization can be copied from https://app.dash0.com -> organization settings
-> "Auth Tokens".
You can freely choose the name of the secret and the key of the token within the secret.

Create the secret by using the following command:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ rules:
- update
- watch

# Pmrmissions required top create a Dash0 operator configuration resources
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get

# Permissions required to queue events to report about the operator's actions, and to attach dangling events to their
# respective involved objects.
- apiGroups:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,28 @@ spec:
- --health-probe-bind-address=:8081
- --metrics-bind-address=127.0.0.1:8080
- --leader-elect
{{- if .Values.operator.dash0Backend.enabled }}
{{- if not .Values.operator.dash0Backend.endpoint }}
{{- fail "Error: operator.dash0Backend.enabled is set to true, but you did not provide a value for operator.dash0Backend.endpoint. Please refer to the installation instructions at https://github.com/dash0hq/dash0-operator/tree/main/helm-chart/dash0-operator." -}}
{{- end}}
- --operator-configuration-endpoint={{ .Values.operator.dash0Backend.endpoint }}
{{- if .Values.operator.dash0Backend.token }}
- --operator-configuration-token={{ .Values.operator.dash0Backend.token }}
{{- else if (and .Values.operator.dash0Backend.secretRef.name .Values.operator.dash0Backend.secretRef.key) }}
{{- $secret := lookup "v1" "Secret" .Release.Namespace .Values.operator.dash0Backend.secretRef.name -}}
{{- if $secret -}}
{{- if not (index $secret.data .Values.operator.dash0Backend.secretRef.key) -}}
{{- fail (printf "Error: There is a secret named \"%s\" in the target namespace \"%s\", but it does not have the required key \"%s\". Please refer to the installation instructions at https://github.com/dash0hq/dash0-operator/tree/main/helm-chart/dash0-operator." .Values.operator.dash0Backend.secretRef.name .Release.Namespace .Values.operator.dash0Backend.secretRef.key) -}}
{{- end -}}
{{- else -}}
{{- fail (printf "Error: There is no secret named \"%s\" in the target namespace \"%s\". Please refer to the installation instructions at https://github.com/dash0hq/dash0-operator/tree/main/helm-chart/dash0-operator." .Values.operator.dash0Backend.secretRef.name .Release.Namespace) -}}
{{- end }}
- --operator-configuration-secret-ref-name={{ .Values.operator.dash0Backend.secretRef.name }}
- --operator-configuration-secret-ref-key={{ .Values.operator.dash0Backend.secretRef.key }}
{{- else }}
{{- fail "Error: operator.dash0Backend.enabled is set to true, but neither operator.dash0Backend.token nor operator.dash0Backend.secretRef.name & operator.dash0Backend.secretRef.key have been provided. Please refer to the installation instructions at https://github.com/dash0hq/dash0-operator/tree/main/helm-chart/dash0-operator." -}}
{{- end }}
{{- end }}
env:
- name: DASH0_OPERATOR_NAMESPACE
valueFrom:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ cluster roles should match snapshot:
- patch
- update
- watch
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
- apiGroups:
- ""
resources:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,27 @@ tests:
path: spec.template.spec.containers[0].resources.requests.memory
value: 32Mi

- it: should add args for creating an operator configuration resource with a token to deployment
documentSelector:
path: metadata.name
value: dash0-operator-controller
set:
operator:
dash0Backend:
enabled: true
endpoint: https://ingress.dash0.com
token: "very-secret-dash0-auth-token"
asserts:
- equal:
path: spec.template.spec.containers[0].args[3]
value: --operator-configuration-endpoint=https://ingress.dash0.com
- equal:
path: spec.template.spec.containers[0].args[4]
value: --operator-configuration-token=very-secret-dash0-auth-token
# Note: We deliberately do not have a test for the operator.dash0Backend.secretRef variant, since this would trigger
# a check whether the secret actually exists in the cluster, which of course would fail when runnig helm chart unit
# tests.

- it: should render the "dash0.com/cert-digest" label
documentSelector:
path: metadata.name
Expand Down
Loading

0 comments on commit 6930991

Please sign in to comment.