Skip to content

Commit

Permalink
[GEN-2343]: add K8sAttributes action to Frontend (#2423)
Browse files Browse the repository at this point in the history
This pull request introduces a new `K8sAttributes` action type to the
codebase, including its schema, model, and resolver implementations.
Additionally, the `DeleteAttribute` action type is removed. The most
important changes include the addition of new structs and types, updates
to GraphQL schema and resolvers, and changes to the frontend to support
the new action type.

### Backend Changes:
* Added `K8sAttributes` related structs and methods in
`frontend/graph/model/models_gen.go` and
`frontend/services/actions/k8sattributes.go` to handle the new action
type
[[1]](diffhunk://#diff-642ccd7ed71fdfa394bd7f7fd99c9c33e20ff18c876a91cb989d379a44390469R364-R403)
[[2]](diffhunk://#diff-696d77a28418879dedeb81bb982d9bcc94207ff957abf8191cd95acd5e59f1b7R1-R202).
* Updated GraphQL schema to include `K8sAttributes` action type
definitions in `frontend/graph/schema.graphqls`.
* Modified resolver functions in `frontend/graph/schema.resolvers.go` to
support CRUD operations for `K8sAttributes`
[[1]](diffhunk://#diff-8e6e95029056db2c0301fc338e0ca5a04356ce5d45ee9514bbd167f2d85bae70R182-R199)
[[2]](diffhunk://#diff-8e6e95029056db2c0301fc338e0ca5a04356ce5d45ee9514bbd167f2d85bae70R710-R711)
[[3]](diffhunk://#diff-8e6e95029056db2c0301fc338e0ca5a04356ce5d45ee9514bbd167f2d85bae70R739-R740)
[[4]](diffhunk://#diff-8e6e95029056db2c0301fc338e0ca5a04356ce5d45ee9514bbd167f2d85bae70R768-R773).

### Frontend Changes:
* Updated TypeScript types and hooks to handle the new `K8sAttributes`
action type in `frontend/webapp/@types/actions.ts` and
`frontend/webapp/hooks/actions/useActionCRUD.ts`
[[1]](diffhunk://#diff-b99a36c3fda3b946157ee7c73048d901dd88fb42ca4c1824b49f10c22428a51cR17-L20)
[[2]](diffhunk://#diff-97e103ce27156651b4a989f874cbddcdc9a3c2583c0a14e36d036bdd4f66933eR63-R76)
[[3]](diffhunk://#diff-97e103ce27156651b4a989f874cbddcdc9a3c2583c0a14e36d036bdd4f66933eR133-R137)
[[4]](diffhunk://#diff-97e103ce27156651b4a989f874cbddcdc9a3c2583c0a14e36d036bdd4f66933eR157-R160).
* Adjusted imports and type references in various frontend components to
accommodate changes in the action types
[[1]](diffhunk://#diff-28b4299bcdd8388bb12e495d5ac9f8fb8dc4e0491a8aaa9f69ffaf77ab630a6eL9-R9)
[[2]](diffhunk://#diff-28b4299bcdd8388bb12e495d5ac9f8fb8dc4e0491a8aaa9f69ffaf77ab630a6eL19-R19)
[[3]](diffhunk://#diff-9118797e852fc875768d26edabbef50a7e5084e6a399ba181a1323403e4a32bbL8-R13).

### Dependency Updates:
* Updated `@odigos/ui-containers` and `@odigos/ui-utils` versions in
`frontend/webapp/package.json`.

---------

Co-authored-by: Ron Federman <[email protected]>
  • Loading branch information
BenElferink and RonFed authored Feb 11, 2025
1 parent 4683ffe commit 0db998a
Show file tree
Hide file tree
Showing 14 changed files with 1,827 additions and 422 deletions.
1,717 changes: 1,410 additions & 307 deletions frontend/graph/generated.go

Large diffs are not rendered by default.

49 changes: 45 additions & 4 deletions frontend/graph/model/models_gen.go

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

32 changes: 28 additions & 4 deletions frontend/graph/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,34 @@ interface Action {
signals: [SignalType!]!
}

type K8sLabelAttribute {
labelKey: String!
attributeKey: String!
}

type K8sAnnotationAttribute {
annotationKey: String!
attributeKey: String!
}

type K8sAttributes {
collectContainerAttributes: Boolean!
collectWorkloadId: Boolean!
collectClusterId: Boolean!
labelsAttributes: [K8sLabelAttribute!]!
annotationsAttributes: [K8sAnnotationAttribute!]!
}

type K8sAttributesAction implements Action {
id: ID!
type: String!
name: String
notes: String
disable: Boolean!
signals: [SignalType!]!
details: K8sAttributes!
}

type ClusterInfo {
attributeName: String!
attributeStringValue: String
Expand All @@ -377,10 +405,6 @@ type AddClusterInfoAction implements Action {
details: [ClusterInfo!]!
}

type DeleteAttribute {
attributeName: String!
}

type DeleteAttributeAction implements Action {
id: ID!
type: String!
Expand Down
28 changes: 28 additions & 0 deletions frontend/graph/schema.resolvers.go

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

2 changes: 1 addition & 1 deletion frontend/services/actions/addclusterinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

type AddClusterInfoDetails struct {
ClusterAttributes []model.ClusterInfo `json:"clusterAttributes"`
ClusterAttributes []v1alpha1.OtelAttributeWithValue `json:"clusterAttributes"`
}

func CreateAddClusterInfo(ctx context.Context, action model.ActionInput) (model.Action, error) {
Expand Down
1 change: 1 addition & 0 deletions frontend/services/actions/constants.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package services

const (
ActionTypeK8sAttributes = "K8sAttributesResolver"
ActionTypeAddClusterInfo = "AddClusterInfo"
ActionTypeDeleteAttribute = "DeleteAttribute"
ActionTypeRenameAttribute = "RenameAttribute"
Expand Down
184 changes: 184 additions & 0 deletions frontend/services/actions/k8sattributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package services

import (
"context"
"encoding/json"
"fmt"

"github.com/odigos-io/odigos/api/actions/v1alpha1"
"github.com/odigos-io/odigos/frontend/graph/model"
"github.com/odigos-io/odigos/frontend/kube"
"github.com/odigos-io/odigos/frontend/services"
"github.com/odigos-io/odigos/k8sutils/pkg/env"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type K8sAttributesDetails struct {
CollectContainerAttributes bool `json:"collectContainerAttributes"`
CollectWorkloadUID bool `json:"collectWorkloadId"`
CollectClusterUID bool `json:"collectClusterId"`
LabelsAttributes []v1alpha1.K8sLabelAttribute `json:"labelsAttributes,omitempty"`
AnnotationsAttributes []v1alpha1.K8sAnnotationAttribute `json:"annotationsAttributes,omitempty"`
}

func CreateK8sAttributes(ctx context.Context, action model.ActionInput) (model.Action, error) {
var details K8sAttributesDetails
err := json.Unmarshal([]byte(action.Details), &details)
if err != nil {
return nil, fmt.Errorf("invalid details for K8sAttributes: %v", err)
}

signals, err := services.ConvertSignals(action.Signals)
if err != nil {
return nil, fmt.Errorf("failed to convert signals: %v", err)
}

k8sAttributesAction := &v1alpha1.K8sAttributesResolver{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "ka-",
},
Spec: v1alpha1.K8sAttributesSpec{
ActionName: services.DerefString(action.Name),
Notes: services.DerefString(action.Notes),
Disabled: action.Disable,
Signals: signals,
CollectContainerAttributes: details.CollectContainerAttributes,
CollectWorkloadUID: details.CollectWorkloadUID,
CollectClusterUID: details.CollectClusterUID,
LabelsAttributes: details.LabelsAttributes,
AnnotationsAttributes: details.AnnotationsAttributes,
},
}

ns := env.GetCurrentNamespace()

generatedAction, err := kube.DefaultClient.ActionsClient.K8sAttributesResolvers(ns).Create(ctx, k8sAttributesAction, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("failed to create K8sAttributes: %v", err)
}

labelAttrs := make([]*model.K8sLabelAttribute, len(details.LabelsAttributes))
for i, attr := range details.LabelsAttributes {
labelAttrs[i] = &model.K8sLabelAttribute{
LabelKey: attr.LabelKey,
AttributeKey: attr.AttributeKey,
}
}

annotAttrs := make([]*model.K8sAnnotationAttribute, len(details.AnnotationsAttributes))
for i, attr := range details.AnnotationsAttributes {
annotAttrs[i] = &model.K8sAnnotationAttribute{
AnnotationKey: attr.AnnotationKey,
AttributeKey: attr.AttributeKey,
}
}

response := &model.K8sAttributesAction{
ID: generatedAction.Name,
Type: ActionTypeAddClusterInfo,
Name: action.Name,
Notes: action.Notes,
Disable: action.Disable,
Signals: action.Signals,
Details: &model.K8sAttributes{
CollectContainerAttributes: details.CollectContainerAttributes,
CollectWorkloadID: details.CollectWorkloadUID,
CollectClusterID: details.CollectClusterUID,
LabelsAttributes: labelAttrs,
AnnotationsAttributes: annotAttrs,
},
}

return response, nil
}

func UpdateK8sAttributes(ctx context.Context, id string, action model.ActionInput) (model.Action, error) {
ns := env.GetCurrentNamespace()

// Fetch the existing action
existingAction, err := kube.DefaultClient.ActionsClient.K8sAttributesResolvers(ns).Get(ctx, id, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("failed to fetch K8sAttributes: %v", err)
}

// Parse the details from action.Details
var details K8sAttributesDetails
err = json.Unmarshal([]byte(action.Details), &details)
if err != nil {
return nil, fmt.Errorf("invalid details for K8sAttributes: %v", err)
}

// Convert signals from action input
signals, err := services.ConvertSignals(action.Signals)
if err != nil {
return nil, fmt.Errorf("failed to convert signals: %v", err)
}

// Update the existing action with new values
existingAction.Spec.ActionName = services.DerefString(action.Name)
existingAction.Spec.Notes = services.DerefString(action.Notes)
existingAction.Spec.Disabled = action.Disable
existingAction.Spec.Signals = signals
existingAction.Spec.CollectContainerAttributes = details.CollectContainerAttributes
existingAction.Spec.CollectWorkloadUID = details.CollectWorkloadUID
existingAction.Spec.CollectClusterUID = details.CollectClusterUID
existingAction.Spec.LabelsAttributes = details.LabelsAttributes
existingAction.Spec.AnnotationsAttributes = details.AnnotationsAttributes

// Update the action in Kubernetes
updatedAction, err := kube.DefaultClient.ActionsClient.K8sAttributesResolvers(ns).Update(ctx, existingAction, metav1.UpdateOptions{})
if err != nil {
return nil, fmt.Errorf("failed to update K8sAttributes: %v", err)
}

// Prepare the response model
labelAttrs := make([]*model.K8sLabelAttribute, len(details.LabelsAttributes))
for i, attr := range details.LabelsAttributes {
labelAttrs[i] = &model.K8sLabelAttribute{
LabelKey: attr.LabelKey,
AttributeKey: attr.AttributeKey,
}
}

annotAttrs := make([]*model.K8sAnnotationAttribute, len(details.AnnotationsAttributes))
for i, attr := range details.AnnotationsAttributes {
annotAttrs[i] = &model.K8sAnnotationAttribute{
AnnotationKey: attr.AnnotationKey,
AttributeKey: attr.AttributeKey,
}
}

response := &model.K8sAttributesAction{
ID: updatedAction.Name,
Type: ActionTypeAddClusterInfo,
Name: action.Name,
Notes: action.Notes,
Disable: action.Disable,
Signals: action.Signals,
Details: &model.K8sAttributes{
CollectContainerAttributes: details.CollectContainerAttributes,
CollectWorkloadID: details.CollectWorkloadUID,
CollectClusterID: details.CollectClusterUID,
LabelsAttributes: labelAttrs,
AnnotationsAttributes: annotAttrs,
},
}

return response, nil
}

func DeleteK8sAttributes(ctx context.Context, id string) error {
ns := env.GetCurrentNamespace()

// Delete the action by its ID from Kubernetes
err := kube.DefaultClient.ActionsClient.K8sAttributesResolvers(ns).Delete(ctx, id, metav1.DeleteOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return fmt.Errorf("K8sAttributes action with ID %s not found", id)
}
return fmt.Errorf("failed to delete K8sAttributes action: %v", err)
}

return nil
}
6 changes: 5 additions & 1 deletion frontend/webapp/@types/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ export interface ParsedActionSpec {
signals: string[];
disabled?: boolean;

collectContainerAttributes?: boolean | null;
collectWorkloadUID?: boolean | null;
collectClusterUID?: boolean | null;
labelsAttributes?: { labelKey: string; attributeKey: string }[] | null;
annotationsAttributes?: { annotationKey: string; attributeKey: string }[] | null;
clusterAttributes?: { attributeName: string; attributeStringValue: string }[] | null;
attributeNamesToDelete?: string[] | null;
renames?: { [oldKey: string]: string } | null;

piiCategories?: string[] | null;
fallback_sampling_ratio?: number | null;
sampling_percentage?: string | null;
Expand Down
Loading

0 comments on commit 0db998a

Please sign in to comment.