Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lifecycle-operator): propagate metadata from deployment annotations #2832

Merged
merged 16 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ configmapref
configmapreference
containedctx
containerspec
contextcommon
contextdata
controllercommon
controllererrors
Expand Down Expand Up @@ -294,6 +293,7 @@ keptnappversionstatus
keptnconfig
keptnconfiglist
keptnconfigspec
keptncontext
keptncontroller
keptndemo
keptndemoapp
Expand Down Expand Up @@ -487,7 +487,6 @@ previousversion
printargs
printcolumn
privs
Process
proj
promapi
promhttp
Expand Down
12 changes: 12 additions & 0 deletions .github/scripts/.helm-tests/default/result.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7207,6 +7207,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down Expand Up @@ -7690,6 +7696,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down
12 changes: 12 additions & 0 deletions .github/scripts/.helm-tests/lifecycle-only/result.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7153,6 +7153,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down Expand Up @@ -7636,6 +7642,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down
12 changes: 12 additions & 0 deletions .github/scripts/.helm-tests/lifecycle-with-certs/result.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7187,6 +7187,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down Expand Up @@ -7671,6 +7677,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,7 @@ _Appears in:_
| `preDeploymentEvaluations` _string array_ | PreDeploymentEvaluations is a list of all evaluations to be performed during the pre-deployment phase of the KeptnWorkload. The items of this list refer to the names of KeptnEvaluationDefinitions located in the same namespace as the KeptnWorkload, or in the Keptn namespace. || ✓ |
| `postDeploymentEvaluations` _string array_ | PostDeploymentEvaluations is a list of all evaluations to be performed during the post-deployment phase of the KeptnWorkload. The items of this list refer to the names of KeptnEvaluationDefinitions located in the same namespace as the KeptnWorkload, or in the Keptn namespace. || ✓ |
| `resourceReference` _[ResourceReference](#resourcereference)_ | ResourceReference is a reference to the Kubernetes resource (Deployment, DaemonSet, StatefulSet or ReplicaSet) the KeptnWorkload is representing. || x |
| `metadata` _object (keys:string, values:string)_ | Refer to Kubernetes API documentation for fields of `metadata`. || ✓ |


#### KeptnWorkloadStatus
Expand Down Expand Up @@ -868,6 +869,7 @@ _Appears in:_
| `preDeploymentEvaluations` _string array_ | PreDeploymentEvaluations is a list of all evaluations to be performed during the pre-deployment phase of the KeptnWorkload. The items of this list refer to the names of KeptnEvaluationDefinitions located in the same namespace as the KeptnWorkload, or in the Keptn namespace. || ✓ |
| `postDeploymentEvaluations` _string array_ | PostDeploymentEvaluations is a list of all evaluations to be performed during the post-deployment phase of the KeptnWorkload. The items of this list refer to the names of KeptnEvaluationDefinitions located in the same namespace as the KeptnWorkload, or in the Keptn namespace. || ✓ |
| `resourceReference` _[ResourceReference](#resourcereference)_ | ResourceReference is a reference to the Kubernetes resource (Deployment, DaemonSet, StatefulSet or ReplicaSet) the KeptnWorkload is representing. || x |
| `metadata` _object (keys:string, values:string)_ | Refer to Kubernetes API documentation for fields of `metadata`. || ✓ |
| `workloadName` _string_ | WorkloadName is the name of the KeptnWorkload. || x |
| `previousVersion` _string_ | PreviousVersion is the version of the KeptnWorkload that has been deployed prior to this version. || ✓ |
| `traceId` _object (keys:string, values:string)_ | TraceId contains the OpenTelemetry trace ID. || ✓ |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const CreateWorkloadEvalSpanName = "create_%s_deployment_evaluation"
const AppTypeAnnotation = "keptn.sh/app-type"
const KeptnGate = "keptn-prechecks-gate"
const ContainerNameAnnotation = "keptn.sh/container"
const MetadataAnnotation = "keptn.sh/metadata"

const MinKeptnNameLen = 80
const MaxK8sObjectLength = 253
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ type KeptnWorkloadSpec struct {
// ResourceReference is a reference to the Kubernetes resource
// (Deployment, DaemonSet, StatefulSet or ReplicaSet) the KeptnWorkload is representing.
ResourceReference ResourceReference `json:"resourceReference"`
// +optional
// Metadata contains additional key-value pairs for contextual information.
Metadata map[string]string `json:"metadata,omitempty"`
}

// KeptnWorkloadStatus defines the observed state of KeptnWorkload
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions lifecycle-operator/chart/templates/keptnworkload-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,12 @@ spec:
app:
description: AppName is the name of the KeptnApp containing the KeptnWorkload.
type: string
metadata:
additionalProperties:
type: string
description: Metadata contains additional key-value pairs for contextual
information.
type: object
postDeploymentEvaluations:
description: |-
PostDeploymentEvaluations is a list of all evaluations to be performed
Expand Down
27 changes: 27 additions & 0 deletions lifecycle-operator/controllers/common/context/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package context

import "context"

type keptnAppContextKeyType string

var keptnAppContextKey = keptnAppContextKeyType("keptnAppContextMeta")

func WithAppMetadata(ctx context.Context, appContextMeta ...map[string]string) context.Context {
mergedMap := map[string]string{}
for _, meta := range appContextMeta {
for key, value := range meta {
mergedMap[key] = value
}
}
return context.WithValue(ctx, keptnAppContextKey, mergedMap)
}

func GetAppMetadataFromContext(ctx context.Context) (map[string]string, bool) {
value := ctx.Value(keptnAppContextKey)

appContextMeta, ok := value.(map[string]string)
if ok {
return appContextMeta, true
}
return map[string]string{}, false
}
25 changes: 25 additions & 0 deletions lifecycle-operator/controllers/common/context/context_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package context

import (
"context"
"testing"

"github.com/stretchr/testify/require"
)

func TestContextWithAppMetadata(t *testing.T) {
ctx := context.Background()

metadata := map[string]string{
"foo": "bar",
}

ctx = WithAppMetadata(ctx, metadata)

require.NotNil(t, ctx)

metadata, ok := GetAppMetadataFromContext(ctx)

require.True(t, ok)
require.Equal(t, "bar", metadata["foo"])
}
12 changes: 12 additions & 0 deletions lifecycle-operator/controllers/common/telemetry/spanhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"context"
"sync"

keptncontext "github.com/keptn/lifecycle-toolkit/lifecycle-operator/controllers/common/context"
"github.com/keptn/lifecycle-toolkit/lifecycle-operator/controllers/lifecycle/interfaces"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -45,6 +47,16 @@ func (r *Handler) GetSpan(ctx context.Context, tracer ITracer, reconcileObject c
childCtx, span := tracer.Start(ctx, spanName, trace.WithSpanKind(trace.SpanKindConsumer))
piWrapper.SetSpanAttributes(span)

// also get attributes from context
if meta, ok := keptncontext.GetAppMetadataFromContext(ctx); ok {
for key, value := range meta {
span.SetAttributes(attribute.KeyValue{
Key: attribute.Key(key),
Value: attribute.StringValue(value),
})
}
}

if phase != "" {
traceContextCarrier := propagation.MapCarrier{}
otel.GetTextMapPropagator().Inject(childCtx, traceContextCarrier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (

"github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1"
apicommon "github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1/common"
keptncontext "github.com/keptn/lifecycle-toolkit/lifecycle-operator/controllers/common/context"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/trace"
"sigs.k8s.io/controller-runtime/pkg/client"
)

Expand Down Expand Up @@ -103,3 +105,35 @@ func TestSpanHandler_GetSpan(t *testing.T) {
require.Equal(t, span, span5)

}

func TestSpanHandler_GetSpanWithAttributes(t *testing.T) {
wi := &v1beta1.KeptnWorkloadVersion{}
wi.Spec.TraceId = make(map[string]string, 1)
wi.Spec.TraceId["traceparent"] = "test-parent"
wi.Spec.AppName = "test"
wi.Spec.WorkloadName = "test"
wi.Spec.Version = "test"

r := Handler{}
phase := apicommon.PhaseAppDeployment.ShortName

tp := trace.NewTracerProvider()

tracer := tp.Tracer("keptn")

ctx := context.TODO()

ctx = keptncontext.WithAppMetadata(ctx, map[string]string{"foo": "bar"})
ctx, span, err := r.GetSpan(ctx, tracer, wi, phase)

require.Nil(t, err)
require.NotNil(t, span)
require.NotNil(t, ctx)

attributes := span.(trace.ReadOnlySpan).Attributes()
require.NotNil(t, attributes)

// the total number of attributes should be 5 (i.e. the workload specific ones + the additional one)
require.Len(t, attributes, 5)
require.Equal(t, "bar", attributes[4].Value.AsString())
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func (r *KeptnWorkloadReconciler) Reconcile(ctx context.Context, req ctrl.Reques
if err != nil {
return reconcile.Result{}, err
}

err = r.Client.Create(ctx, workloadVersion)
if err != nil {
r.Log.Error(err, "could not create WorkloadVersion")
Expand Down Expand Up @@ -142,6 +143,7 @@ func (r *KeptnWorkloadReconciler) createWorkloadVersion(ctx context.Context, wor
}

workloadVersion := generateWorkloadVersion(previousVersion, traceContextCarrier, workload)

err := controllerutil.SetControllerReference(workload, &workloadVersion, r.Scheme)
if err != nil {
r.Log.Error(err, "could not set controller reference for WorkloadVersion: "+workloadVersion.Name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ func TestKeptnWorkload(t *testing.T) {
Spec: klcv1beta1.KeptnWorkloadSpec{
Version: "version",
AppName: "app",
Metadata: map[string]string{
"foo": "bar",
},
},
}

Expand All @@ -31,6 +34,9 @@ func TestKeptnWorkload(t *testing.T) {
KeptnWorkloadSpec: klcv1beta1.KeptnWorkloadSpec{
Version: "version",
AppName: "app",
Metadata: map[string]string{
"foo": "bar",
},
},
WorkloadName: "workload",
PreviousVersion: "prev",
Expand Down
Loading
Loading