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

Support overriding task annotations and labels via with_overrides #6171

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

arbaobao
Copy link

@arbaobao arbaobao commented Jan 15, 2025

Tracking issue

Why are the changes needed?

Improvement to allow setting labels and annotations dynamically at run time for things like cost allocation.

What changes were proposed in this pull request?

Adds labels and annotations to with_overrides().

How was this patch tested?

Excute a workflow and using with_override(labels={"lKeyA": "lValA"},annotations={"lKeyB": "lValB"}).

Setup process

python

@task
def say_hello() -> str:
    return "Hello, World!"

@workflow
def hello_world_wf() -> str:
    res = say_hello().with_overrides(labels={"lKeyA": "lValA"},annotations={"lKeyB": "lValB"})
    return res

It can be tested by using kubectl describe pods {pod_name} -n flytesnacks-development

Screenshots

Check all the applicable boxes

  • I updated the documentation accordingly.
  • All new and existing tests passed.
  • All commits are signed-off.

Related PRs

flytekit 3061

Docs link

Summary by Bito

This PR implements support for overriding task annotations and labels via TaskNodeOverrides and with_overrides(), enabling dynamic pod metadata configuration at runtime. The implementation includes protobuf definition updates across multiple language bindings (TypeScript, Go, JavaScript, Python), interface methods, and workflow compiler updates. The changes include updated test helper functions, new test cases, and mock interfaces for annotation and label getters. This enhancement particularly benefits scenarios like cost allocation through runtime pod metadata modification.

Unit tests added: True

Estimated effort to review (1-5, lower is better): 5

Signed-off-by: Nelson Chen <asd3431090@gmail.com>
Signed-off-by: Nelson Chen <asd3431090@gmail.com>
@flyte-bot
Copy link
Collaborator

flyte-bot commented Jan 15, 2025

Code Review Agent Run #d2a6a3

Actionable Suggestions - 7
  • flytepropeller/pkg/apis/flyteworkflow/v1alpha1/nodes.go - 2
  • flytepropeller/pkg/apis/flyteworkflow/v1alpha1/iface.go - 1
    • Consider consolidating duplicate interface methods · Line 446-447
  • flyteplugins/go/tasks/pluginmachinery/flytek8s/pod_helper_test.go - 1
    • Consider consolidating duplicate mock setup · Line 57-58
  • flytepropeller/pkg/compiler/transformers/k8s/node.go - 2
    • Consider initializing maps with make() · Line 34-35
    • Consider consolidating override handling logic · Line 66-72
  • flyteidl/gen/pb-go/flyteidl/core/workflow.pb.go - 1
Additional Suggestions - 1
  • flytepropeller/pkg/apis/flyteworkflow/v1alpha1/nodes.go - 1
Review Details
  • Files reviewed - 19 · Commit Range: 5f9eb9d..ce8aca8
    • flyteidl/gen/pb-es/flyteidl/core/workflow_pb.ts
    • flyteidl/gen/pb-go/flyteidl/core/workflow.pb.go
    • flyteidl/gen/pb-js/flyteidl.d.ts
    • flyteidl/gen/pb-js/flyteidl.js
    • flyteidl/gen/pb_python/flyteidl/core/workflow_pb2.py
    • flyteidl/gen/pb_python/flyteidl/core/workflow_pb2.pyi
    • flyteidl/gen/pb_rust/flyteidl.core.rs
    • flyteidl/protos/flyteidl/core/workflow.proto
    • flyteplugins/go/tasks/pluginmachinery/core/exec_metadata.go
    • flyteplugins/go/tasks/pluginmachinery/core/mocks/task_overrides.go
    • flyteplugins/go/tasks/pluginmachinery/flytek8s/config/k8spluginconfig_flags.go
    • flyteplugins/go/tasks/pluginmachinery/flytek8s/config/k8spluginconfig_flags_test.go
    • flyteplugins/go/tasks/pluginmachinery/flytek8s/plugin_exec_context.go
    • flyteplugins/go/tasks/pluginmachinery/flytek8s/pod_helper.go
    • flyteplugins/go/tasks/pluginmachinery/flytek8s/pod_helper_test.go
    • flyteplugins/tests/end_to_end.go
    • flytepropeller/pkg/apis/flyteworkflow/v1alpha1/iface.go
    • flytepropeller/pkg/apis/flyteworkflow/v1alpha1/nodes.go
    • flytepropeller/pkg/compiler/transformers/k8s/node.go
  • Files skipped - 3
    • flyteidl/clients/go/assets/admin.swagger.json - Reason: Filter setting
    • flyteidl/gen/pb-go/gateway/flyteidl/service/admin.swagger.json - Reason: Filter setting
    • flyteidl/gen/pb-go/gateway/flyteidl/service/agent.swagger.json - Reason: Filter setting
  • Tools
    • Golangci-lint (Linter) - ✖︎ Failed
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

AI Code Review powered by Bito Logo

Copy link

codecov bot commented Jan 15, 2025

Codecov Report

Attention: Patch coverage is 7.93651% with 58 lines in your changes missing coverage. Please review.

Project coverage is 34.39%. Comparing base (05c85a8) to head (2533937).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
...pis/flyteworkflow/v1alpha1/mocks/ExecutableNode.go 0.00% 38 Missing ⚠️
flyteidl/gen/pb-go/flyteidl/core/workflow.pb.go 9.09% 10 Missing ⚠️
...ytepropeller/pkg/compiler/transformers/k8s/node.go 40.00% 4 Missing and 2 partials ⚠️
...propeller/pkg/apis/flyteworkflow/v1alpha1/nodes.go 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6171      +/-   ##
==========================================
- Coverage   37.05%   34.39%   -2.66%     
==========================================
  Files        1318     1097     -221     
  Lines      132583   114688   -17895     
==========================================
- Hits        49122    39451    -9671     
+ Misses      79211    71868    -7343     
+ Partials     4250     3369     -881     
Flag Coverage Δ
unittests-datacatalog 51.58% <ø> (ø)
unittests-flyteadmin 54.31% <ø> (-0.03%) ⬇️
unittests-flytecopilot 30.99% <ø> (ø)
unittests-flytectl 62.29% <ø> (-0.05%) ⬇️
unittests-flyteidl 7.23% <9.09%> (-0.01%) ⬇️
unittests-flyteplugins ?
unittests-flytepropeller 42.63% <7.69%> (-0.03%) ⬇️
unittests-flytestdlib 55.13% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@flyte-bot
Copy link
Collaborator

flyte-bot commented Jan 15, 2025

Changelist by Bito

This pull request implements the following key changes.

Key Change Files Impacted
Feature Improvement - Task Node Overrides Enhancement

workflow_pb.ts - Added labels and annotations fields to TaskNodeOverrides class

workflow.pb.go - Implemented Go protobuf bindings for TaskNodeOverrides labels and annotations

flyteidl.d.ts - Added TypeScript definitions for TaskNodeOverrides labels and annotations

flyteidl.js - Added JavaScript implementation for TaskNodeOverrides labels and annotations

workflow_pb2.py - Updated Python protobuf descriptor for TaskNodeOverrides

Feature Improvement - Task Node Overrides Enhancement

workflow_pb2.py - Updated Python protobuf descriptor and serialization options for TaskNodeOverrides

workflow_pb2.pyi - Added type definitions for labels and annotations in TaskNodeOverrides

flyteidl.core.rs - Added Rust implementation for TaskNodeOverrides labels and annotations

workflow.proto - Added labels and annotations fields to TaskNodeOverrides protobuf definition

exec_metadata.go - Added interface methods for getting annotations and labels

pod_helper.go - Implemented pod metadata override functionality

nodes.go - Added annotations and labels fields to NodeSpec

node.go - Updated node builder to handle annotation and label overrides

Testing - Test Coverage for TaskNodeOverrides

pod_helper_test.go - Updated existing tests to support new override parameters

end_to_end.go - Added end-to-end test coverage for annotation and label overrides

Comment on lines +164 to +167
Annotations map[string]string `json:"annotation,omitempty" protobuf:"bytes,22,opt,name=annotation"`
// If specified, includes overrides for labels to allocate to the node
//+optional
Labels map[string]string `json:"label,omitempty" protobuf:"bytes,22,opt,name=label"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate protobuf field numbers need updating

Consider updating the protobuf field numbers for annotation and label fields as they both use field number 22 which is already used by tolerations. This could cause protobuf serialization issues.

Code suggestion
Check the AI-generated fix before applying
 -	Annotations map[string]string `json:"annotation,omitempty" protobuf:"bytes,22,opt,name=annotation"`
 -	Labels map[string]string `json:"label,omitempty" protobuf:"bytes,22,opt,name=label"`
 +	Annotations map[string]string `json:"annotation,omitempty" protobuf:"bytes,23,opt,name=annotation"`
 +	Labels map[string]string `json:"label,omitempty" protobuf:"bytes,24,opt,name=label"`

Code Review Run #d2a6a3


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Comment on lines +278 to +284
func (in *NodeSpec) GetAnnotations() map[string]string {
return in.Annotations
}

func (in *NodeSpec) GetLabels() map[string]string {
return in.Labels
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding nil check for maps

Consider adding validation for nil maps in GetAnnotations() and GetLabels() to avoid potential nil pointer dereference. Similar issues were also found in:

  • flyteplugins/go/tasks/pluginmachinery/flytek8s/pod_helper.go (line 467)
  • flyteplugins/go/tasks/pluginmachinery/flytek8s/pod_helper.go (line 439)
  • flyteplugins/go/tasks/pluginmachinery/flytek8s/pod_helper.go (line 474)
Code suggestion
Check the AI-generated fix before applying
 -func (in *NodeSpec) GetAnnotations() map[string]string {
 -	return in.Annotations
 +func (in *NodeSpec) GetAnnotations() map[string]string {
 +	if in.Annotations == nil {
 +		return make(map[string]string)
 +	}
 +	return in.Annotations
  }
 -func (in *NodeSpec) GetLabels() map[string]string {
 -	return in.Labels
 +func (in *NodeSpec) GetLabels() map[string]string {
 +	if in.Labels == nil {
 +		return make(map[string]string)
 +	}
 +	return in.Labels
  }

Code Review Run #d2a6a3


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Comment on lines +446 to +447
GetAnnotations() map[string]string
GetLabels() map[string]string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider consolidating duplicate interface methods

Consider consolidating the GetAnnotations() and GetLabels() methods since they already exist in the Meta interface. This appears to be semantic duplication.

Code suggestion
Check the AI-generated fix before applying
 -	GetAnnotations() map[string]string
 -	GetLabels() map[string]string
 +	Meta
  }

Code Review Run #d2a6a3


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Comment on lines 57 to 58
to.On("GetAnnotations").Return(map[string]string{"annotation-1": "val1"})
to.On("GetLabels").Return(map[string]string{"label-1": "val1"})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider consolidating duplicate mock setup

Consider consolidating the mock setup for annotations and labels into the existing dummyTaskExecutionMetadata function since these are part of task metadata configuration.

Code suggestion
Check the AI-generated fix before applying
 	taskExecutionMetadata.On("GetNamespace").Return("test-namespace")
 +	taskExecutionMetadata.On("GetAnnotations").Return(map[string]string{"annotation-1": "val1"})
 +	taskExecutionMetadata.On("GetLabels").Return(map[string]string{"label-1": "val1"})
 	to := &pluginsCoreMock.TaskOverrides{}
 	to.On("GetResources").Return(resources)
 	to.On("GetExtendedResources").Return(extendedResources)
 	to.On("GetContainerImage").Return(containerImage)
 -	to.On("GetAnnotations").Return(map[string]string{"annotation-1": "val1"})
 -	to.On("GetLabels").Return(map[string]string{"label-1": "val1"})

Code Review Run #d2a6a3


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Comment on lines +34 to +35
var annotations map[string]string
var labels map[string]string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider initializing maps with make()

Consider initializing the maps annotations and labels with make() to avoid potential nil map issues when adding key-value pairs later.

Code suggestion
Check the AI-generated fix before applying
Suggested change
var annotations map[string]string
var labels map[string]string
annotations := make(map[string]string)
labels := make(map[string]string)

Code Review Run #d2a6a3


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Comment on lines +66 to +72
if overrides.GetAnnotations() != nil {
annotations = overrides.GetAnnotations()
}

if overrides.GetLabels() != nil {
labels = overrides.GetLabels()
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider consolidating override handling logic

Consider combining the annotation and label override checks into a single function to improve code organization and reusability. The current implementation has similar logic repeated for both annotations and labels.

Code suggestion
Check the AI-generated fix before applying
Suggested change
if overrides.GetAnnotations() != nil {
annotations = overrides.GetAnnotations()
}
if overrides.GetLabels() != nil {
labels = overrides.GetLabels()
}
func getOverrideMap(original, override map[string]string) map[string]string {
if override != nil {
return override
}
return original
}
annotations = getOverrideMap(annotations, overrides.GetAnnotations())
labels = getOverrideMap(labels, overrides.GetLabels())

Code Review Run #d2a6a3


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Comment on lines +1655 to +1658
// Optional labels to add to the pod definition.
Labels map[string]string `protobuf:"bytes,4,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// Optional annotations to add to the pod definition.
Annotations map[string]string `protobuf:"bytes,5,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider consolidating pod metadata fields

Consider consolidating the pod metadata fields (labels and annotations) into a separate K8SObjectMetadata struct since these fields are already defined in that type. This would help maintain consistency and reduce duplication across the codebase.

Code suggestion
Check the AI-generated fix before applying
 -    // Optional labels to add to the pod definition.
 -    Labels map[string]string `protobuf:"bytes,4,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
 -    // Optional annotations to add to the pod definition.
 -    Annotations map[string]string `protobuf:"bytes,5,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
 +    // Pod metadata including labels and annotations
 +    PodMetadata *K8SObjectMetadata `protobuf:"bytes,4,opt,name=pod_metadata,json=podMetadata,proto3" json:"pod_metadata,omitempty"`
  }

Code Review Run #d2a6a3


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Signed-off-by: Nelson Chen <asd3431090@gmail.com>
Signed-off-by: Nelson Chen <asd3431090@gmail.com>
@flyte-bot
Copy link
Collaborator

flyte-bot commented Jan 15, 2025

Code Review Agent Run #1ba60d

Actionable Suggestions - 2
  • flyteplugins/go/tasks/pluginmachinery/flytek8s/pod_helper_test.go - 2
Review Details
  • Files reviewed - 2 · Commit Range: ce8aca8..2533937
    • flyteplugins/go/tasks/pluginmachinery/flytek8s/pod_helper_test.go
    • flytepropeller/pkg/apis/flyteworkflow/v1alpha1/mocks/ExecutableNode.go
  • Files skipped - 0
  • Tools
    • Golangci-lint (Linter) - ✖︎ Failed
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

AI Code Review powered by Bito Logo

@@ -756,7 +756,7 @@ func updatePod(t *testing.T) {
}

func TestUpdatePodWithDefaultAffinityAndInterruptibleNodeSelectorRequirement(t *testing.T) {
taskExecutionMetadata := dummyTaskExecutionMetadata(&v1.ResourceRequirements{}, nil, "")
taskExecutionMetadata := dummyTaskExecutionMetadata(&v1.ResourceRequirements{}, nil, "", nil, nil)
assert.NoError(t, config.SetK8sPluginConfig(&config.K8sPluginConfig{
DefaultAffinity: &v1.Affinity{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update test cases for new signature

Consider updating all test cases to use the new function signature for dummyTaskExecutionMetadata with annotations and labels parameters. Some test cases are still using the old signature which may cause compilation errors.

Code suggestion
Check the AI-generated fix before applying
Suggested change
DefaultAffinity: &v1.Affinity{
taskExecutionMetadata := dummyTaskExecutionMetadata(&v1.ResourceRequirements{}, nil, "", nil, nil)

Code Review Run #1ba60d


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Comment on lines +1065 to +1087
func TestToK8sPodAnnotations(t *testing.T) {
t.Run("Override annotations", func(t *testing.T) {
taskContext := dummyExecContext(dummyTaskTemplate(), &v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("1024m"),
}}, nil, "foo:latest", map[string]string{"a": "b"}, nil)
_, m, _, err := ToK8sPodSpec(context.TODO(), taskContext)
assert.NoError(t, err)
assert.Equal(t, "b", m.Annotations["a"])
})
}

func TestToK8sPodLabels(t *testing.T) {
t.Run("Override labels", func(t *testing.T) {
taskContext := dummyExecContext(dummyTaskTemplate(), &v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("1024m"),
}}, nil, "foo:latest", nil, map[string]string{"a": "b"})
_, m, _, err := ToK8sPodSpec(context.TODO(), taskContext)
assert.NoError(t, err)
assert.Equal(t, "b", m.Labels["a"])
})
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider combining similar test functions

Consider combining TestToK8sPodAnnotations and TestToK8sPodLabels into a single test function since they have very similar test logic and setup. This would reduce code duplication while still maintaining test coverage.

Code suggestion
Check the AI-generated fix before applying
Suggested change
func TestToK8sPodAnnotations(t *testing.T) {
t.Run("Override annotations", func(t *testing.T) {
taskContext := dummyExecContext(dummyTaskTemplate(), &v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("1024m"),
}}, nil, "foo:latest", map[string]string{"a": "b"}, nil)
_, m, _, err := ToK8sPodSpec(context.TODO(), taskContext)
assert.NoError(t, err)
assert.Equal(t, "b", m.Annotations["a"])
})
}
func TestToK8sPodLabels(t *testing.T) {
t.Run("Override labels", func(t *testing.T) {
taskContext := dummyExecContext(dummyTaskTemplate(), &v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("1024m"),
}}, nil, "foo:latest", nil, map[string]string{"a": "b"})
_, m, _, err := ToK8sPodSpec(context.TODO(), taskContext)
assert.NoError(t, err)
assert.Equal(t, "b", m.Labels["a"])
})
}
func TestToK8sPodMetadata(t *testing.T) {
tests := []struct {
name string
annotations map[string]string
labels map[string]string
}{
{"Override annotations", map[string]string{"a": "b"}, nil},
{"Override labels", nil, map[string]string{"a": "b"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
taskContext := dummyExecContext(dummyTaskTemplate(), &v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("1024m"),
}}, nil, "foo:latest", tt.annotations, tt.labels)
_, m, _, err := ToK8sPodSpec(context.TODO(), taskContext)
assert.NoError(t, err)
if tt.annotations != nil {
assert.Equal(t, "b", m.Annotations["a"])
}
if tt.labels != nil {
assert.Equal(t, "b", m.Labels["a"])
}
})
}
}

Code Review Run #1ba60d


Is this a valid issue, or was it incorrectly flagged by the Agent?

  • it was incorrectly flagged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants