From 5922937c08735c65aa7b0f14c3916a91813bc71a Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Wed, 3 Jan 2024 14:57:03 -0800 Subject: [PATCH 1/9] update kfp kubernetes sdk to include pod labels and annotations --- .../kubernetes_executor_config.pb.go | 155 +++++++++++++++--- .../proto/kubernetes_executor_config.proto | 8 + .../python/kfp/kubernetes/__init__.py | 4 + .../python/kfp/kubernetes/pod_metadata.py | 69 ++++++++ .../python/test/unit/test_pod_metadata.py | 138 ++++++++++++++++ 5 files changed, 349 insertions(+), 25 deletions(-) create mode 100644 kubernetes_platform/python/kfp/kubernetes/pod_metadata.py create mode 100644 kubernetes_platform/python/test/unit/test_pod_metadata.py diff --git a/kubernetes_platform/go/kubernetesplatform/kubernetes_executor_config.pb.go b/kubernetes_platform/go/kubernetesplatform/kubernetes_executor_config.pb.go index bff68860500..c536b54152a 100644 --- a/kubernetes_platform/go/kubernetesplatform/kubernetes_executor_config.pb.go +++ b/kubernetes_platform/go/kubernetesplatform/kubernetes_executor_config.pb.go @@ -44,6 +44,7 @@ type KubernetesExecutorConfig struct { SecretAsEnv []*SecretAsEnv `protobuf:"bytes,2,rep,name=secret_as_env,json=secretAsEnv,proto3" json:"secret_as_env,omitempty"` PvcMount []*PvcMount `protobuf:"bytes,3,rep,name=pvc_mount,json=pvcMount,proto3" json:"pvc_mount,omitempty"` NodeSelector *NodeSelector `protobuf:"bytes,4,opt,name=node_selector,json=nodeSelector,proto3" json:"node_selector,omitempty"` + PodMetadata *PodMetadata `protobuf:"bytes,5,opt,name=pod_metadata,json=podMetadata,proto3" json:"pod_metadata,omitempty"` } func (x *KubernetesExecutorConfig) Reset() { @@ -106,6 +107,13 @@ func (x *KubernetesExecutorConfig) GetNodeSelector() *NodeSelector { return nil } +func (x *KubernetesExecutorConfig) GetPodMetadata() *PodMetadata { + if x != nil { + return x.PodMetadata + } + return nil +} + type SecretAsVolume struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -674,6 +682,63 @@ func (x *NodeSelector) GetLabels() map[string]string { return nil } +type PodMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // values of metadata spec such as labels and annotations for the pod object + // corresponds to Pod.metadata field https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#Pod + Labels map[string]string `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Annotations map[string]string `protobuf:"bytes,2,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *PodMetadata) Reset() { + *x = PodMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_kubernetes_executor_config_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PodMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PodMetadata) ProtoMessage() {} + +func (x *PodMetadata) ProtoReflect() protoreflect.Message { + mi := &file_kubernetes_executor_config_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PodMetadata.ProtoReflect.Descriptor instead. +func (*PodMetadata) Descriptor() ([]byte, []int) { + return file_kubernetes_executor_config_proto_rawDescGZIP(), []int{8} +} + +func (x *PodMetadata) GetLabels() map[string]string { + if x != nil { + return x.Labels + } + return nil +} + +func (x *PodMetadata) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + type SecretAsEnv_SecretKeyToEnvMap struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -688,7 +753,7 @@ type SecretAsEnv_SecretKeyToEnvMap struct { func (x *SecretAsEnv_SecretKeyToEnvMap) Reset() { *x = SecretAsEnv_SecretKeyToEnvMap{} if protoimpl.UnsafeEnabled { - mi := &file_kubernetes_executor_config_proto_msgTypes[8] + mi := &file_kubernetes_executor_config_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -701,7 +766,7 @@ func (x *SecretAsEnv_SecretKeyToEnvMap) String() string { func (*SecretAsEnv_SecretKeyToEnvMap) ProtoMessage() {} func (x *SecretAsEnv_SecretKeyToEnvMap) ProtoReflect() protoreflect.Message { - mi := &file_kubernetes_executor_config_proto_msgTypes[8] + mi := &file_kubernetes_executor_config_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -739,7 +804,7 @@ var file_kubernetes_executor_config_proto_rawDesc = []byte{ 0x74, 0x6f, 0x12, 0x0e, 0x6b, 0x66, 0x70, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x9f, 0x02, 0x0a, 0x18, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x45, + 0x22, 0xdf, 0x02, 0x0a, 0x18, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x48, 0x0a, 0x10, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6b, 0x66, 0x70, 0x5f, 0x6b, 0x75, @@ -757,7 +822,11 @@ var file_kubernetes_executor_config_proto_rawDesc = []byte{ 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6b, 0x66, 0x70, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0c, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x22, 0x50, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x41, 0x73, 0x56, 0x6f, + 0x6f, 0x72, 0x12, 0x3e, 0x0a, 0x0c, 0x70, 0x6f, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6b, 0x66, 0x70, 0x5f, 0x6b, + 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x2e, 0x50, 0x6f, 0x64, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x70, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x22, 0x50, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x41, 0x73, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, @@ -841,12 +910,30 @@ var file_kubernetes_executor_config_proto_rawDesc = []byte{ 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x42, 0x49, 0x5a, 0x47, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x66, 0x6c, 0x6f, 0x77, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x6c, - 0x69, 0x6e, 0x65, 0x73, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x5f, - 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x2f, 0x6b, 0x75, 0x62, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x02, 0x38, 0x01, 0x22, 0x99, 0x02, 0x0a, 0x0b, 0x50, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x3f, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6b, 0x66, 0x70, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x65, 0x73, 0x2e, 0x50, 0x6f, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6b, 0x66, 0x70, 0x5f, + 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x2e, 0x50, 0x6f, 0x64, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, + 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, + 0x49, 0x5a, 0x47, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x75, + 0x62, 0x65, 0x66, 0x6c, 0x6f, 0x77, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, + 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, + 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -861,7 +948,7 @@ func file_kubernetes_executor_config_proto_rawDescGZIP() []byte { return file_kubernetes_executor_config_proto_rawDescData } -var file_kubernetes_executor_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_kubernetes_executor_config_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_kubernetes_executor_config_proto_goTypes = []interface{}{ (*KubernetesExecutorConfig)(nil), // 0: kfp_kubernetes.KubernetesExecutorConfig (*SecretAsVolume)(nil), // 1: kfp_kubernetes.SecretAsVolume @@ -871,25 +958,31 @@ var file_kubernetes_executor_config_proto_goTypes = []interface{}{ (*CreatePvc)(nil), // 5: kfp_kubernetes.CreatePvc (*DeletePvc)(nil), // 6: kfp_kubernetes.DeletePvc (*NodeSelector)(nil), // 7: kfp_kubernetes.NodeSelector - (*SecretAsEnv_SecretKeyToEnvMap)(nil), // 8: kfp_kubernetes.SecretAsEnv.SecretKeyToEnvMap - nil, // 9: kfp_kubernetes.NodeSelector.LabelsEntry - (*structpb.Struct)(nil), // 10: google.protobuf.Struct + (*PodMetadata)(nil), // 8: kfp_kubernetes.PodMetadata + (*SecretAsEnv_SecretKeyToEnvMap)(nil), // 9: kfp_kubernetes.SecretAsEnv.SecretKeyToEnvMap + nil, // 10: kfp_kubernetes.NodeSelector.LabelsEntry + nil, // 11: kfp_kubernetes.PodMetadata.LabelsEntry + nil, // 12: kfp_kubernetes.PodMetadata.AnnotationsEntry + (*structpb.Struct)(nil), // 13: google.protobuf.Struct } var file_kubernetes_executor_config_proto_depIdxs = []int32{ 1, // 0: kfp_kubernetes.KubernetesExecutorConfig.secret_as_volume:type_name -> kfp_kubernetes.SecretAsVolume 2, // 1: kfp_kubernetes.KubernetesExecutorConfig.secret_as_env:type_name -> kfp_kubernetes.SecretAsEnv 4, // 2: kfp_kubernetes.KubernetesExecutorConfig.pvc_mount:type_name -> kfp_kubernetes.PvcMount 7, // 3: kfp_kubernetes.KubernetesExecutorConfig.node_selector:type_name -> kfp_kubernetes.NodeSelector - 8, // 4: kfp_kubernetes.SecretAsEnv.key_to_env:type_name -> kfp_kubernetes.SecretAsEnv.SecretKeyToEnvMap - 3, // 5: kfp_kubernetes.PvcMount.task_output_parameter:type_name -> kfp_kubernetes.TaskOutputParameterSpec - 10, // 6: kfp_kubernetes.CreatePvc.annotations:type_name -> google.protobuf.Struct - 3, // 7: kfp_kubernetes.DeletePvc.task_output_parameter:type_name -> kfp_kubernetes.TaskOutputParameterSpec - 9, // 8: kfp_kubernetes.NodeSelector.labels:type_name -> kfp_kubernetes.NodeSelector.LabelsEntry - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 8, // 4: kfp_kubernetes.KubernetesExecutorConfig.pod_metadata:type_name -> kfp_kubernetes.PodMetadata + 9, // 5: kfp_kubernetes.SecretAsEnv.key_to_env:type_name -> kfp_kubernetes.SecretAsEnv.SecretKeyToEnvMap + 3, // 6: kfp_kubernetes.PvcMount.task_output_parameter:type_name -> kfp_kubernetes.TaskOutputParameterSpec + 13, // 7: kfp_kubernetes.CreatePvc.annotations:type_name -> google.protobuf.Struct + 3, // 8: kfp_kubernetes.DeletePvc.task_output_parameter:type_name -> kfp_kubernetes.TaskOutputParameterSpec + 10, // 9: kfp_kubernetes.NodeSelector.labels:type_name -> kfp_kubernetes.NodeSelector.LabelsEntry + 11, // 10: kfp_kubernetes.PodMetadata.labels:type_name -> kfp_kubernetes.PodMetadata.LabelsEntry + 12, // 11: kfp_kubernetes.PodMetadata.annotations:type_name -> kfp_kubernetes.PodMetadata.AnnotationsEntry + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_kubernetes_executor_config_proto_init() } @@ -995,6 +1088,18 @@ func file_kubernetes_executor_config_proto_init() { } } file_kubernetes_executor_config_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PodMetadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_kubernetes_executor_config_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SecretAsEnv_SecretKeyToEnvMap); i { case 0: return &v.state @@ -1027,7 +1132,7 @@ func file_kubernetes_executor_config_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_kubernetes_executor_config_proto_rawDesc, NumEnums: 0, - NumMessages: 10, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/kubernetes_platform/proto/kubernetes_executor_config.proto b/kubernetes_platform/proto/kubernetes_executor_config.proto index 8bba56463c8..8b215c8ae12 100644 --- a/kubernetes_platform/proto/kubernetes_executor_config.proto +++ b/kubernetes_platform/proto/kubernetes_executor_config.proto @@ -25,6 +25,7 @@ message KubernetesExecutorConfig { repeated SecretAsEnv secret_as_env = 2; repeated PvcMount pvc_mount = 3; NodeSelector node_selector = 4; + PodMetadata pod_metadata = 5; } message SecretAsVolume { @@ -114,3 +115,10 @@ message NodeSelector { // corresponds to Pod.spec.nodeSelector field https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#scheduling map labels = 1; } + +message PodMetadata { + // values of metadata spec such as labels and annotations for the pod object + // corresponds to Pod.metadata field https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#Pod + map labels = 1; + map annotations = 2; +} diff --git a/kubernetes_platform/python/kfp/kubernetes/__init__.py b/kubernetes_platform/python/kfp/kubernetes/__init__.py index 587e5132b07..c2c266becf0 100644 --- a/kubernetes_platform/python/kfp/kubernetes/__init__.py +++ b/kubernetes_platform/python/kfp/kubernetes/__init__.py @@ -21,8 +21,12 @@ 'use_secret_as_env', 'use_secret_as_volume', 'add_node_selector', + 'add_pod_label', + 'add_pod_annotation', ] +from kfp.kubernetes.pod_metadata import add_pod_label +from kfp.kubernetes.pod_metadata import add_pod_annotation from kfp.kubernetes.node_selector import add_node_selector from kfp.kubernetes.secret import use_secret_as_env from kfp.kubernetes.secret import use_secret_as_volume diff --git a/kubernetes_platform/python/kfp/kubernetes/pod_metadata.py b/kubernetes_platform/python/kfp/kubernetes/pod_metadata.py new file mode 100644 index 00000000000..dc8571b1284 --- /dev/null +++ b/kubernetes_platform/python/kfp/kubernetes/pod_metadata.py @@ -0,0 +1,69 @@ +# Copyright 2024 The Kubeflow Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from google.protobuf import json_format +from kfp.dsl import PipelineTask +from kfp.kubernetes import common + + +def add_pod_label( + task: PipelineTask, + label_key: str, + label_value: str, +) -> PipelineTask: + """Add a label to the task Pod's `metadata + `_. + + Each label is a key-value pair, corresponding to the metadata's `ObjectMeta PipelineTask: + """Add an annotation to the task Pod's `metadata + `_. + + Each annotation is a key-value pair, corresponding to the metadata's `ObjectMeta Date: Wed, 3 Jan 2024 15:03:52 -0800 Subject: [PATCH 2/9] fix unit test output order --- kubernetes_platform/python/test/unit/test_pod_metadata.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kubernetes_platform/python/test/unit/test_pod_metadata.py b/kubernetes_platform/python/test/unit/test_pod_metadata.py index 4d5864fe8bd..7ea03d066c6 100644 --- a/kubernetes_platform/python/test/unit/test_pod_metadata.py +++ b/kubernetes_platform/python/test/unit/test_pod_metadata.py @@ -81,13 +81,13 @@ def my_pipeline(): 'executors': { 'exec-comp': { 'podMetadata': { - 'labels': { - 'kubeflow.com/kfp': 'pipeline-node', - 'kubeflow.com/common': 'test' - }, 'annotations': { 'run_id': '123456', 'experiment_id': '234567' + }, + 'labels': { + 'kubeflow.com/kfp': 'pipeline-node', + 'kubeflow.com/common': 'test' } } } From e818522b770b42ceea58f421b96adab285a3363b Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Mon, 8 Jan 2024 11:24:05 -0800 Subject: [PATCH 3/9] add podmetadata changes --- .../src/v2/compiler/argocompiler/container.go | 29 ++++++------ backend/src/v2/driver/driver.go | 47 +++++++++++++++++++ backend/src/v2/driver/driver_test.go | 40 ++++++++++++++++ go.mod | 1 + go.sum | 2 - kubernetes_platform/python/README.md | 26 ++++++++++ 6 files changed, 129 insertions(+), 16 deletions(-) diff --git a/backend/src/v2/compiler/argocompiler/container.go b/backend/src/v2/compiler/argocompiler/container.go index 03d85f18019..4ef093aed0c 100644 --- a/backend/src/v2/compiler/argocompiler/container.go +++ b/backend/src/v2/compiler/argocompiler/container.go @@ -15,8 +15,9 @@ package argocompiler import ( - wfapi "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" "os" + + wfapi "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" "github.com/kubeflow/pipelines/api/v2alpha1/go/pipelinespec" "github.com/kubeflow/pipelines/backend/src/v2/component" k8score "k8s.io/api/core/v1" @@ -24,10 +25,10 @@ import ( const ( volumeNameKFPLauncher = "kfp-launcher" - DefaultLauncherImage = "gcr.io/ml-pipeline/kfp-launcher@sha256:80cf120abd125db84fa547640fd6386c4b2a26936e0c2b04a7d3634991a850a4" + DefaultLauncherImage = "gcr.io/ml-pipeline/kfp-launcher@sha256:80cf120abd125db84fa547640fd6386c4b2a26936e0c2b04a7d3634991a850a4" LauncherImageEnvVar = "V2_LAUNCHER_IMAGE" - DefaultDriverImage = "gcr.io/ml-pipeline/kfp-driver@sha256:8e60086b04d92b657898a310ca9757631d58547e76bbbb8bfc376d654bef1707" - DriverImageEnvVar = "V2_DRIVER_IMAGE" + DefaultDriverImage = "gcr.io/ml-pipeline/kfp-driver@sha256:8e60086b04d92b657898a310ca9757631d58547e76bbbb8bfc376d654bef1707" + DriverImageEnvVar = "V2_DRIVER_IMAGE" ) func (c *workflowCompiler) Container(name string, component *pipelinespec.ComponentSpec, container *pipelinespec.PipelineDeploymentConfig_PipelineContainerSpec) error { @@ -58,19 +59,19 @@ type containerDriverInputs struct { } func GetLauncherImage() string { - launcherImage := os.Getenv(LauncherImageEnvVar) - if launcherImage == "" { - launcherImage = DefaultLauncherImage - } - return launcherImage + launcherImage := os.Getenv(LauncherImageEnvVar) + if launcherImage == "" { + launcherImage = DefaultLauncherImage + } + return launcherImage } func GetDriverImage() string { - driverImage := os.Getenv(DriverImageEnvVar) - if driverImage == "" { - driverImage = DefaultDriverImage - } - return driverImage + driverImage := os.Getenv(DriverImageEnvVar) + if driverImage == "" { + driverImage = DefaultDriverImage + } + return driverImage } func (c *workflowCompiler) containerDriverTask(name string, inputs containerDriverInputs) (*wfapi.DAGTask, *containerDriverOutputs) { diff --git a/backend/src/v2/driver/driver.go b/backend/src/v2/driver/driver.go index adf626dfeab..508ac50add2 100644 --- a/backend/src/v2/driver/driver.go +++ b/backend/src/v2/driver/driver.go @@ -109,6 +109,7 @@ type Execution struct { // only specified when this is a Container execution Cached *bool PodSpecPatch string + PodMetadata *metav1.ObjectMeta } func (e *Execution) WillTrigger() bool { @@ -322,6 +323,7 @@ func Container(ctx context.Context, opts Options, mlmd *metadata.Client, cacheCl } podSpec, err := initPodSpecPatch(opts.Container, opts.Component, executorInput, execution.ID, opts.PipelineName, opts.RunID) + var podMetadata *metav1.ObjectMeta if err != nil { return execution, err } @@ -334,12 +336,19 @@ func Container(ctx context.Context, opts Options, mlmd *metadata.Client, cacheCl if err != nil { return execution, err } + err = extendPodMetadata(podMetadata, opts.KubernetesExecutorConfig) + if err != nil { + return execution, err + } } podSpecPatchBytes, err := json.Marshal(podSpec) if err != nil { return execution, fmt.Errorf("JSON marshaling pod spec patch: %w", err) } execution.PodSpecPatch = string(podSpecPatchBytes) + if podMetadata != nil { + execution.PodMetadata = podMetadata + } return execution, nil } @@ -453,6 +462,44 @@ func initPodSpecPatch( return podSpec, nil } +// Extends the PodMetadata to include Kubernetes-specific executor config. +func extendPodMetadata( + podMetadata *metav1.ObjectMeta, + kubernetesExecutorConfig *kubernetesplatform.KubernetesExecutorConfig, +) error { + // Get pod metadata information + if kubernetesExecutorConfig.GetPodMetadata() != nil { + if kubernetesExecutorConfig.GetPodMetadata().GetLabels() != nil { + if podMetadata.Labels == nil { + podMetadata.Labels = kubernetesExecutorConfig.GetPodMetadata().GetLabels() + } else { + podMetadata.Labels = extendMetadataMap(podMetadata.Labels, kubernetesExecutorConfig.GetPodMetadata().GetLabels()) + } + } + if kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() != nil { + if podMetadata.Annotations == nil { + podMetadata.Annotations = kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() + } else { + podMetadata.Annotations = extendMetadataMap(podMetadata.Annotations, kubernetesExecutorConfig.GetPodMetadata().GetAnnotations()) + } + } + } + return nil +} + +// Extends metadata map values, highPriorityMap should overwrites lowPriorityMap values +// The original Map inputs should have higher priority since its defined by admin +// TODO: Use maps.Copy after moving to go 1.21+ +func extendMetadataMap( + highPriorityMap map[string]string, + lowPriorityMap map[string]string, +) map[string]string { + for k, v := range highPriorityMap { + lowPriorityMap[k] = v + } + return lowPriorityMap +} + // Extends the PodSpec to include Kubernetes-specific executor config. func extendPodSpecPatch( podSpec *k8score.PodSpec, diff --git a/backend/src/v2/driver/driver_test.go b/backend/src/v2/driver/driver_test.go index ec8516fb34d..0011cc911da 100644 --- a/backend/src/v2/driver/driver_test.go +++ b/backend/src/v2/driver/driver_test.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/assert" k8score "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func Test_initPodSpecPatch_acceleratorConfig(t *testing.T) { @@ -605,3 +606,42 @@ func Test_extendPodSpecPatch_Secret(t *testing.T) { }) } } + +func Test_extendPodMetadata(t *testing.T) { + tests := []struct { + name string + podMetadata *metav1.ObjectMeta + kubernetesExecutorConfig *kubernetesplatform.KubernetesExecutorConfig + expected *metav1.ObjectMeta + }{ + { + "Valid - add pod labels and annotations", + &metav1.ObjectMeta{}, + &kubernetesplatform.KubernetesExecutorConfig{ + PodMetadata: &kubernetesplatform.PodMetadata{ + Annotations: map[string]string{ + "run_id": "123456", + }, + Labels: map[string]string{ + "kubeflow.com/kfp": "pipeline-node", + }, + }, + }, + &metav1.ObjectMeta{ + Annotations: map[string]string{ + "run_id": "123456", + }, + Labels: map[string]string{ + "kubeflow.com/kfp": "pipeline-node", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := extendPodMetadata(tt.podMetadata, tt.kubernetesExecutorConfig) + assert.Nil(t, err) + assert.Equal(t, tt.expected, tt.podMetadata) + }) + } +} diff --git a/go.mod b/go.mod index 2140e27775d..e0ee1e4e859 100644 --- a/go.mod +++ b/go.mod @@ -61,6 +61,7 @@ require ( ) replace ( + github.com/kubeflow/pipelines/kubernetes_platform => ./kubernetes_platform/ k8s.io/kubernetes => k8s.io/kubernetes v1.11.1 sigs.k8s.io/controller-tools => sigs.k8s.io/controller-tools v0.2.9 ) diff --git a/go.sum b/go.sum index bef3f379d66..6e4a8176bed 100644 --- a/go.sum +++ b/go.sum @@ -936,8 +936,6 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/ktrysmt/go-bitbucket v0.9.32/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno= github.com/kubeflow/pipelines/api v0.0.0-20230331215358-758c91f76784 h1:ZVCoqnKnC2vctD7AqAHbWf05qw15VO5XSxCqkjObwtw= github.com/kubeflow/pipelines/api v0.0.0-20230331215358-758c91f76784/go.mod h1:T7TOQB36gGe97yUdfVAnYK5uuT0+uQbLNHDUHxYkmE4= -github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20230404213301-bd9f74e34de6 h1:ApWW5ZH45ruvQCmkp7RewHlPKGwqBNSSRxEHGJFiAOA= -github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20230404213301-bd9f74e34de6/go.mod h1:CJkKr356RlpZP/gQRuHf3Myrn1qJtoUVe4EMCmtwarg= github.com/kubeflow/pipelines/third_party/ml-metadata v0.0.0-20230810215105-e1f0c010f800 h1:YAW+X9xCW8Yq5tQaBBQaLTNU9CJj8Nr7lx1+k66ZHJ0= github.com/kubeflow/pipelines/third_party/ml-metadata v0.0.0-20230810215105-e1f0c010f800/go.mod h1:chIDffBaVQ/asNl1pTTdbAymYcuBKf8BR3YtSP+3FEU= github.com/labstack/echo v3.2.1+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= diff --git a/kubernetes_platform/python/README.md b/kubernetes_platform/python/README.md index df575b196a6..652ad93e638 100644 --- a/kubernetes_platform/python/README.md +++ b/kubernetes_platform/python/README.md @@ -102,3 +102,29 @@ def my_pipeline(): delete_pvc1 = kubernetes.DeletePVC( pvc_name=pvc1.outputs['name']).after(task2) ``` + +### Pod Metadata: Add pod labels and annotations to the container pod's definition +```python +from kfp import dsl +from kfp import kubernetes + + +@dsl.component +def comp(): + pass + + +@dsl.pipeline +def my_pipeline(): + task = comp() + kubernetes.add_pod_label( + task, + label_key='kubeflow.com/kfp', + label_value='pipeline-node', + ) + kubernetes.add_pod_annotation( + task, + annotation_key='run_id', + annotation_value='123456', + ) +``` \ No newline at end of file From dcbf6de488cb1f03ed1d8bdce3f9b4129c4f66b8 Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Mon, 8 Jan 2024 14:51:50 -0800 Subject: [PATCH 4/9] update argo compiler to support pod metadata --- .../src/v2/compiler/argocompiler/argo_test.go | 5 + .../src/v2/compiler/argocompiler/container.go | 52 +++- backend/src/v2/compiler/argocompiler/dag.go | 2 +- .../testdata/create_pod_metadata.yaml | 283 ++++++++++++++++++ .../testdata/create_pod_metadata.json | 22 ++ backend/src/v2/driver/driver.go | 47 --- go.mod | 1 + 7 files changed, 361 insertions(+), 51 deletions(-) create mode 100644 backend/src/v2/compiler/argocompiler/testdata/create_pod_metadata.yaml create mode 100644 backend/src/v2/compiler/testdata/create_pod_metadata.json diff --git a/backend/src/v2/compiler/argocompiler/argo_test.go b/backend/src/v2/compiler/argocompiler/argo_test.go index b5da4bf9234..6c92e54574c 100644 --- a/backend/src/v2/compiler/argocompiler/argo_test.go +++ b/backend/src/v2/compiler/argocompiler/argo_test.go @@ -52,6 +52,11 @@ func Test_argo_compiler(t *testing.T) { platformSpecPath: "../testdata/create_mount_delete_dynamic_pvc_platform.json", argoYAMLPath: "testdata/create_mount_delete_dynamic_pvc.yaml", }, + { + jobPath: "../testdata/hello_world.json", + platformSpecPath: "../testdata/create_pod_metadata.json", + argoYAMLPath: "testdata/create_pod_metadata.yaml", + }, } for _, tt := range tests { t.Run(fmt.Sprintf("%+v", tt), func(t *testing.T) { diff --git a/backend/src/v2/compiler/argocompiler/container.go b/backend/src/v2/compiler/argocompiler/container.go index 4ef093aed0c..43f7085dc01 100644 --- a/backend/src/v2/compiler/argocompiler/container.go +++ b/backend/src/v2/compiler/argocompiler/container.go @@ -18,8 +18,10 @@ import ( "os" wfapi "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" + "github.com/golang/protobuf/jsonpb" "github.com/kubeflow/pipelines/api/v2alpha1/go/pipelinespec" "github.com/kubeflow/pipelines/backend/src/v2/component" + "github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform" k8score "k8s.io/api/core/v1" ) @@ -170,14 +172,14 @@ type containerExecutorInputs struct { // name: argo workflows DAG task name // The other arguments are argo workflows task parameters, they can be either a // string or a placeholder. -func (c *workflowCompiler) containerExecutorTask(name string, inputs containerExecutorInputs) *wfapi.DAGTask { +func (c *workflowCompiler) containerExecutorTask(name string, inputs containerExecutorInputs, refName string) *wfapi.DAGTask { when := "" if inputs.condition != "" { when = inputs.condition + " != false" } return &wfapi.DAGTask{ Name: name, - Template: c.addContainerExecutorTemplate(), + Template: c.addContainerExecutorTemplate(refName), When: when, Arguments: wfapi.Arguments{ Parameters: []wfapi.Parameter{ @@ -192,7 +194,7 @@ func (c *workflowCompiler) containerExecutorTask(name string, inputs containerEx // any container component task. // During runtime, it's expected that pod-spec-patch will specify command, args // and resources etc, that are different for different tasks. -func (c *workflowCompiler) addContainerExecutorTemplate() string { +func (c *workflowCompiler) addContainerExecutorTemplate(refName string) string { // container template is parent of container implementation template nameContainerExecutor := "system-container-executor" nameContainerImpl := "system-container-impl" @@ -274,7 +276,51 @@ func (c *workflowCompiler) addContainerExecutorTemplate() string { Env: commonEnvs, }, } + // Update pod metadata if it defined in the Kubernetes Spec + if kubernetesConfigString, ok := c.wf.Annotations[annotationKubernetesSpec+refName]; ok { + k8sExecCfg := &kubernetesplatform.KubernetesExecutorConfig{} + if err := jsonpb.UnmarshalString(kubernetesConfigString, k8sExecCfg); err == nil { + extendPodMetadata(&executor.Metadata, k8sExecCfg) + } + } c.templates[nameContainerImpl] = executor c.wf.Spec.Templates = append(c.wf.Spec.Templates, *container, *executor) return nameContainerExecutor } + +// Extends the PodMetadata to include Kubernetes-specific executor config. +func extendPodMetadata( + podMetadata *wfapi.Metadata, + kubernetesExecutorConfig *kubernetesplatform.KubernetesExecutorConfig, +) { + // Get pod metadata information + if kubernetesExecutorConfig.GetPodMetadata() != nil { + if kubernetesExecutorConfig.GetPodMetadata().GetLabels() != nil { + if podMetadata.Labels == nil { + podMetadata.Labels = kubernetesExecutorConfig.GetPodMetadata().GetLabels() + } else { + podMetadata.Labels = extendMetadataMap(podMetadata.Labels, kubernetesExecutorConfig.GetPodMetadata().GetLabels()) + } + } + if kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() != nil { + if podMetadata.Annotations == nil { + podMetadata.Annotations = kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() + } else { + podMetadata.Annotations = extendMetadataMap(podMetadata.Annotations, kubernetesExecutorConfig.GetPodMetadata().GetAnnotations()) + } + } + } +} + +// Extends metadata map values, highPriorityMap should overwrites lowPriorityMap values +// The original Map inputs should have higher priority since its defined by admin +// TODO: Use maps.Copy after moving to go 1.21+ +func extendMetadataMap( + highPriorityMap map[string]string, + lowPriorityMap map[string]string, +) map[string]string { + for k, v := range highPriorityMap { + lowPriorityMap[k] = v + } + return lowPriorityMap +} diff --git a/backend/src/v2/compiler/argocompiler/dag.go b/backend/src/v2/compiler/argocompiler/dag.go index b334c4beb5f..719a166a9a3 100644 --- a/backend/src/v2/compiler/argocompiler/dag.go +++ b/backend/src/v2/compiler/argocompiler/dag.go @@ -232,7 +232,7 @@ func (c *workflowCompiler) task(name string, task *pipelinespec.PipelineTaskSpec podSpecPatch: driverOutputs.podSpecPatch, cachedDecision: driverOutputs.cached, condition: driverOutputs.condition, - }) + }, task.GetComponentRef().GetName()) executor.Depends = depends([]string{driverTaskName}) return []wfapi.DAGTask{*driver, *executor}, nil case *pipelinespec.PipelineDeploymentConfig_ExecutorSpec_Importer: diff --git a/backend/src/v2/compiler/argocompiler/testdata/create_pod_metadata.yaml b/backend/src/v2/compiler/argocompiler/testdata/create_pod_metadata.yaml new file mode 100644 index 00000000000..8b623b87e6a --- /dev/null +++ b/backend/src/v2/compiler/argocompiler/testdata/create_pod_metadata.yaml @@ -0,0 +1,283 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + annotations: + pipelines.kubeflow.org/components-comp-hello-world: '{"executorLabel":"exec-hello-world","inputDefinitions":{"parameters":{"text":{"type":"STRING"}}}}' + pipelines.kubeflow.org/components-root: '{"dag":{"tasks":{"hello-world":{"cachingOptions":{"enableCache":true},"componentRef":{"name":"comp-hello-world"},"inputs":{"parameters":{"text":{"componentInputParameter":"text"}}},"taskInfo":{"name":"hello-world"}}}},"inputDefinitions":{"parameters":{"text":{"type":"STRING"}}}}' + pipelines.kubeflow.org/implementations-comp-hello-world: '{"args":["--text","{{$.inputs.parameters[''text'']}}"],"command":["sh","-ec","program_path=$(mktemp)\nprintf + \"%s\" \"$0\" \u003e \"$program_path\"\npython3 -u \"$program_path\" \"$@\"\n","def + hello_world(text):\n print(text)\n return text\n\nimport argparse\n_parser + = argparse.ArgumentParser(prog=''Hello world'', description='''')\n_parser.add_argument(\"--text\", + dest=\"text\", type=str, required=True, default=argparse.SUPPRESS)\n_parsed_args + = vars(_parser.parse_args())\n\n_outputs = hello_world(**_parsed_args)\n"],"image":"python:3.7"}' + pipelines.kubeflow.org/kubernetes-comp-hello-world: '{"podMetadata":{"annotations":{"experiment_id":"234567","run_id":"123456"},"labels":{"kubeflow.com/common":"test","kubeflow.com/kfp":"pipeline-node"}}}' + creationTimestamp: null + generateName: hello-world- +spec: + arguments: {} + entrypoint: entrypoint + podMetadata: + annotations: + pipelines.kubeflow.org/v2_component: "true" + labels: + pipelines.kubeflow.org/v2_component: "true" + serviceAccountName: pipeline-runner + templates: + - container: + args: + - --type + - CONTAINER + - --pipeline_name + - namespace/n1/pipeline/hello-world + - --run_id + - '{{workflow.uid}}' + - --dag_execution_id + - '{{inputs.parameters.parent-dag-id}}' + - --component + - '{{inputs.parameters.component}}' + - --task + - '{{inputs.parameters.task}}' + - --container + - '{{inputs.parameters.container}}' + - --iteration_index + - '{{inputs.parameters.iteration-index}}' + - --cached_decision_path + - '{{outputs.parameters.cached-decision.path}}' + - --pod_spec_patch_path + - '{{outputs.parameters.pod-spec-patch.path}}' + - --condition_path + - '{{outputs.parameters.condition.path}}' + - --kubernetes_config + - '{{inputs.parameters.kubernetes-config}}' + command: + - driver + image: gcr.io/ml-pipeline/kfp-driver + name: "" + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 64Mi + inputs: + parameters: + - name: component + - name: task + - name: container + - name: parent-dag-id + - default: "-1" + name: iteration-index + - default: "" + name: kubernetes-config + metadata: {} + name: system-container-driver + outputs: + parameters: + - name: pod-spec-patch + valueFrom: + default: "" + path: /tmp/outputs/pod-spec-patch + - default: "false" + name: cached-decision + valueFrom: + default: "false" + path: /tmp/outputs/cached-decision + - name: condition + valueFrom: + default: "true" + path: /tmp/outputs/condition + - dag: + tasks: + - arguments: + parameters: + - name: pod-spec-patch + value: '{{inputs.parameters.pod-spec-patch}}' + name: executor + template: system-container-impl + when: '{{inputs.parameters.cached-decision}} != true' + inputs: + parameters: + - name: pod-spec-patch + - default: "false" + name: cached-decision + metadata: {} + name: system-container-executor + outputs: {} + - container: + command: + - should-be-overridden-during-runtime + env: + - name: KFP_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: KFP_POD_UID + valueFrom: + fieldRef: + fieldPath: metadata.uid + envFrom: + - configMapRef: + name: metadata-grpc-configmap + optional: true + image: gcr.io/ml-pipeline/should-be-overridden-during-runtime + name: "" + resources: {} + volumeMounts: + - mountPath: /kfp-launcher + name: kfp-launcher + initContainers: + - command: + - launcher-v2 + - --copy + - /kfp-launcher/launch + image: gcr.io/ml-pipeline/kfp-launcher + name: kfp-launcher + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 100m + volumeMounts: + - mountPath: /kfp-launcher + name: kfp-launcher + inputs: + parameters: + - name: pod-spec-patch + metadata: + annotations: + experiment_id: "234567" + run_id: "123456" + labels: + kubeflow.com/common: test + kubeflow.com/kfp: pipeline-node + name: system-container-impl + outputs: {} + podSpecPatch: '{{inputs.parameters.pod-spec-patch}}' + volumes: + - emptyDir: {} + name: kfp-launcher + - dag: + tasks: + - arguments: + parameters: + - name: component + value: '{{workflow.annotations.pipelines.kubeflow.org/components-comp-hello-world}}' + - name: task + value: '{"cachingOptions":{"enableCache":true},"componentRef":{"name":"comp-hello-world"},"inputs":{"parameters":{"text":{"componentInputParameter":"text"}}},"taskInfo":{"name":"hello-world"}}' + - name: container + value: '{{workflow.annotations.pipelines.kubeflow.org/implementations-comp-hello-world}}' + - name: parent-dag-id + value: '{{inputs.parameters.parent-dag-id}}' + - name: kubernetes-config + value: '{{workflow.annotations.pipelines.kubeflow.org/kubernetes-comp-hello-world}}' + name: hello-world-driver + template: system-container-driver + - arguments: + parameters: + - name: pod-spec-patch + value: '{{tasks.hello-world-driver.outputs.parameters.pod-spec-patch}}' + - default: "false" + name: cached-decision + value: '{{tasks.hello-world-driver.outputs.parameters.cached-decision}}' + depends: hello-world-driver.Succeeded + name: hello-world + template: system-container-executor + inputs: + parameters: + - name: parent-dag-id + metadata: {} + name: root + outputs: {} + - container: + args: + - --type + - '{{inputs.parameters.driver-type}}' + - --pipeline_name + - namespace/n1/pipeline/hello-world + - --run_id + - '{{workflow.uid}}' + - --dag_execution_id + - '{{inputs.parameters.parent-dag-id}}' + - --component + - '{{inputs.parameters.component}}' + - --task + - '{{inputs.parameters.task}}' + - --runtime_config + - '{{inputs.parameters.runtime-config}}' + - --iteration_index + - '{{inputs.parameters.iteration-index}}' + - --execution_id_path + - '{{outputs.parameters.execution-id.path}}' + - --iteration_count_path + - '{{outputs.parameters.iteration-count.path}}' + - --condition_path + - '{{outputs.parameters.condition.path}}' + command: + - driver + image: gcr.io/ml-pipeline/kfp-driver + name: "" + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 64Mi + inputs: + parameters: + - name: component + - default: "" + name: runtime-config + - default: "" + name: task + - default: "0" + name: parent-dag-id + - default: "-1" + name: iteration-index + - default: DAG + name: driver-type + metadata: {} + name: system-dag-driver + outputs: + parameters: + - name: execution-id + valueFrom: + path: /tmp/outputs/execution-id + - name: iteration-count + valueFrom: + default: "0" + path: /tmp/outputs/iteration-count + - name: condition + valueFrom: + default: "true" + path: /tmp/outputs/condition + - dag: + tasks: + - arguments: + parameters: + - name: component + value: '{{workflow.annotations.pipelines.kubeflow.org/components-root}}' + - name: runtime-config + value: '{"parameters":{"text":{"stringValue":"hi there"}}}' + - name: driver-type + value: ROOT_DAG + name: root-driver + template: system-dag-driver + - arguments: + parameters: + - name: parent-dag-id + value: '{{tasks.root-driver.outputs.parameters.execution-id}}' + - name: condition + value: "" + depends: root-driver.Succeeded + name: root + template: root + inputs: {} + metadata: {} + name: entrypoint + outputs: {} +status: + finishedAt: null + startedAt: null diff --git a/backend/src/v2/compiler/testdata/create_pod_metadata.json b/backend/src/v2/compiler/testdata/create_pod_metadata.json new file mode 100644 index 00000000000..16ee385d35e --- /dev/null +++ b/backend/src/v2/compiler/testdata/create_pod_metadata.json @@ -0,0 +1,22 @@ +{ + "platforms": { + "kubernetes": { + "deploymentSpec": { + "executors": { + "exec-hello-world": { + "podMetadata": { + "annotations": { + "run_id": "123456", + "experiment_id": "234567" + }, + "labels": { + "kubeflow.com/kfp": "pipeline-node", + "kubeflow.com/common": "test" + } + } + } + } + } + } + } + } \ No newline at end of file diff --git a/backend/src/v2/driver/driver.go b/backend/src/v2/driver/driver.go index 508ac50add2..adf626dfeab 100644 --- a/backend/src/v2/driver/driver.go +++ b/backend/src/v2/driver/driver.go @@ -109,7 +109,6 @@ type Execution struct { // only specified when this is a Container execution Cached *bool PodSpecPatch string - PodMetadata *metav1.ObjectMeta } func (e *Execution) WillTrigger() bool { @@ -323,7 +322,6 @@ func Container(ctx context.Context, opts Options, mlmd *metadata.Client, cacheCl } podSpec, err := initPodSpecPatch(opts.Container, opts.Component, executorInput, execution.ID, opts.PipelineName, opts.RunID) - var podMetadata *metav1.ObjectMeta if err != nil { return execution, err } @@ -336,19 +334,12 @@ func Container(ctx context.Context, opts Options, mlmd *metadata.Client, cacheCl if err != nil { return execution, err } - err = extendPodMetadata(podMetadata, opts.KubernetesExecutorConfig) - if err != nil { - return execution, err - } } podSpecPatchBytes, err := json.Marshal(podSpec) if err != nil { return execution, fmt.Errorf("JSON marshaling pod spec patch: %w", err) } execution.PodSpecPatch = string(podSpecPatchBytes) - if podMetadata != nil { - execution.PodMetadata = podMetadata - } return execution, nil } @@ -462,44 +453,6 @@ func initPodSpecPatch( return podSpec, nil } -// Extends the PodMetadata to include Kubernetes-specific executor config. -func extendPodMetadata( - podMetadata *metav1.ObjectMeta, - kubernetesExecutorConfig *kubernetesplatform.KubernetesExecutorConfig, -) error { - // Get pod metadata information - if kubernetesExecutorConfig.GetPodMetadata() != nil { - if kubernetesExecutorConfig.GetPodMetadata().GetLabels() != nil { - if podMetadata.Labels == nil { - podMetadata.Labels = kubernetesExecutorConfig.GetPodMetadata().GetLabels() - } else { - podMetadata.Labels = extendMetadataMap(podMetadata.Labels, kubernetesExecutorConfig.GetPodMetadata().GetLabels()) - } - } - if kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() != nil { - if podMetadata.Annotations == nil { - podMetadata.Annotations = kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() - } else { - podMetadata.Annotations = extendMetadataMap(podMetadata.Annotations, kubernetesExecutorConfig.GetPodMetadata().GetAnnotations()) - } - } - } - return nil -} - -// Extends metadata map values, highPriorityMap should overwrites lowPriorityMap values -// The original Map inputs should have higher priority since its defined by admin -// TODO: Use maps.Copy after moving to go 1.21+ -func extendMetadataMap( - highPriorityMap map[string]string, - lowPriorityMap map[string]string, -) map[string]string { - for k, v := range highPriorityMap { - lowPriorityMap[k] = v - } - return lowPriorityMap -} - // Extends the PodSpec to include Kubernetes-specific executor config. func extendPodSpecPatch( podSpec *k8score.PodSpec, diff --git a/go.mod b/go.mod index e0ee1e4e859..0be3c6e2c95 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/go-openapi/swag v0.19.15 github.com/go-openapi/validate v0.20.3 github.com/go-sql-driver/mysql v1.6.0 + github.com/gogo/protobuf v1.3.2 github.com/golang/glog v1.0.0 github.com/golang/protobuf v1.5.2 github.com/google/addlicense v0.0.0-20200906110928-a0294312aa76 From c79fc7bdb3647393695a98198da253217672c7a1 Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Tue, 9 Jan 2024 10:02:23 -0800 Subject: [PATCH 5/9] update tests --- .../compiler/argocompiler/container_test.go | 61 +++++++++++++++++++ backend/src/v2/driver/driver_test.go | 40 ------------ 2 files changed, 61 insertions(+), 40 deletions(-) create mode 100644 backend/src/v2/compiler/argocompiler/container_test.go diff --git a/backend/src/v2/compiler/argocompiler/container_test.go b/backend/src/v2/compiler/argocompiler/container_test.go new file mode 100644 index 00000000000..5d5744bfede --- /dev/null +++ b/backend/src/v2/compiler/argocompiler/container_test.go @@ -0,0 +1,61 @@ +// Copyright 2021-2024 The Kubeflow Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package argocompiler + +import ( + "testing" + + wfapi "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" + "github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform" + "github.com/stretchr/testify/assert" +) + +func Test_extendPodMetadata(t *testing.T) { + tests := []struct { + name string + podMetadata *wfapi.Metadata + kubernetesExecutorConfig *kubernetesplatform.KubernetesExecutorConfig + expected *wfapi.Metadata + }{ + { + "Valid - add pod labels and annotations", + &wfapi.Metadata{}, + &kubernetesplatform.KubernetesExecutorConfig{ + PodMetadata: &kubernetesplatform.PodMetadata{ + Annotations: map[string]string{ + "run_id": "123456", + }, + Labels: map[string]string{ + "kubeflow.com/kfp": "pipeline-node", + }, + }, + }, + &wfapi.Metadata{ + Annotations: map[string]string{ + "run_id": "123456", + }, + Labels: map[string]string{ + "kubeflow.com/kfp": "pipeline-node", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + extendPodMetadata(tt.podMetadata, tt.kubernetesExecutorConfig) + assert.Equal(t, tt.expected, tt.podMetadata) + }) + } +} diff --git a/backend/src/v2/driver/driver_test.go b/backend/src/v2/driver/driver_test.go index 0011cc911da..ec8516fb34d 100644 --- a/backend/src/v2/driver/driver_test.go +++ b/backend/src/v2/driver/driver_test.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/assert" k8score "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func Test_initPodSpecPatch_acceleratorConfig(t *testing.T) { @@ -606,42 +605,3 @@ func Test_extendPodSpecPatch_Secret(t *testing.T) { }) } } - -func Test_extendPodMetadata(t *testing.T) { - tests := []struct { - name string - podMetadata *metav1.ObjectMeta - kubernetesExecutorConfig *kubernetesplatform.KubernetesExecutorConfig - expected *metav1.ObjectMeta - }{ - { - "Valid - add pod labels and annotations", - &metav1.ObjectMeta{}, - &kubernetesplatform.KubernetesExecutorConfig{ - PodMetadata: &kubernetesplatform.PodMetadata{ - Annotations: map[string]string{ - "run_id": "123456", - }, - Labels: map[string]string{ - "kubeflow.com/kfp": "pipeline-node", - }, - }, - }, - &metav1.ObjectMeta{ - Annotations: map[string]string{ - "run_id": "123456", - }, - Labels: map[string]string{ - "kubeflow.com/kfp": "pipeline-node", - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := extendPodMetadata(tt.podMetadata, tt.kubernetesExecutorConfig) - assert.Nil(t, err) - assert.Equal(t, tt.expected, tt.podMetadata) - }) - } -} From 843cf65b71f1e23d0f49f6b73e3cebe98b4edf59 Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Fri, 12 Jan 2024 13:27:02 -0800 Subject: [PATCH 6/9] update go mod to use the latest kubernetes_platform package --- backend/src/v2/compiler/argocompiler/container.go | 3 +++ backend/src/v2/compiler/testdata/create_pod_metadata.json | 2 +- go.mod | 4 +--- go.sum | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/src/v2/compiler/argocompiler/container.go b/backend/src/v2/compiler/argocompiler/container.go index 43f7085dc01..d187202ad7a 100644 --- a/backend/src/v2/compiler/argocompiler/container.go +++ b/backend/src/v2/compiler/argocompiler/container.go @@ -289,6 +289,9 @@ func (c *workflowCompiler) addContainerExecutorTemplate(refName string) string { } // Extends the PodMetadata to include Kubernetes-specific executor config. +// Although the current podMetadata object is always empty, this function +// doesn't overwrite the existing podMetadata because for security reasons +// the existing podMetadata should have higher privilege than the user definition. func extendPodMetadata( podMetadata *wfapi.Metadata, kubernetesExecutorConfig *kubernetesplatform.KubernetesExecutorConfig, diff --git a/backend/src/v2/compiler/testdata/create_pod_metadata.json b/backend/src/v2/compiler/testdata/create_pod_metadata.json index 16ee385d35e..246d3b1dd23 100644 --- a/backend/src/v2/compiler/testdata/create_pod_metadata.json +++ b/backend/src/v2/compiler/testdata/create_pod_metadata.json @@ -19,4 +19,4 @@ } } } - } \ No newline at end of file + } diff --git a/go.mod b/go.mod index 0be3c6e2c95..2c21b3904ff 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/go-openapi/swag v0.19.15 github.com/go-openapi/validate v0.20.3 github.com/go-sql-driver/mysql v1.6.0 - github.com/gogo/protobuf v1.3.2 github.com/golang/glog v1.0.0 github.com/golang/protobuf v1.5.2 github.com/google/addlicense v0.0.0-20200906110928-a0294312aa76 @@ -32,7 +31,7 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.4 // indirect github.com/kubeflow/pipelines/api v0.0.0-20230331215358-758c91f76784 - github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20230404213301-bd9f74e34de6 + github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240111221413-aac4408237df github.com/kubeflow/pipelines/third_party/ml-metadata v0.0.0-20230810215105-e1f0c010f800 github.com/lestrrat-go/strftime v1.0.4 github.com/mattn/go-sqlite3 v1.14.16 @@ -62,7 +61,6 @@ require ( ) replace ( - github.com/kubeflow/pipelines/kubernetes_platform => ./kubernetes_platform/ k8s.io/kubernetes => k8s.io/kubernetes v1.11.1 sigs.k8s.io/controller-tools => sigs.k8s.io/controller-tools v0.2.9 ) diff --git a/go.sum b/go.sum index 6e4a8176bed..7e06319d151 100644 --- a/go.sum +++ b/go.sum @@ -936,6 +936,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/ktrysmt/go-bitbucket v0.9.32/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno= github.com/kubeflow/pipelines/api v0.0.0-20230331215358-758c91f76784 h1:ZVCoqnKnC2vctD7AqAHbWf05qw15VO5XSxCqkjObwtw= github.com/kubeflow/pipelines/api v0.0.0-20230331215358-758c91f76784/go.mod h1:T7TOQB36gGe97yUdfVAnYK5uuT0+uQbLNHDUHxYkmE4= +github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240111221413-aac4408237df h1:hskr5e/bAKNi8Bc15lG9uZ28q36v/y8qbKkDDix9NPo= +github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240111221413-aac4408237df/go.mod h1:CJkKr356RlpZP/gQRuHf3Myrn1qJtoUVe4EMCmtwarg= github.com/kubeflow/pipelines/third_party/ml-metadata v0.0.0-20230810215105-e1f0c010f800 h1:YAW+X9xCW8Yq5tQaBBQaLTNU9CJj8Nr7lx1+k66ZHJ0= github.com/kubeflow/pipelines/third_party/ml-metadata v0.0.0-20230810215105-e1f0c010f800/go.mod h1:chIDffBaVQ/asNl1pTTdbAymYcuBKf8BR3YtSP+3FEU= github.com/labstack/echo v3.2.1+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= From 5d1baf04625ccadf5df97ae6df2c1e1de8a5c74c Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Fri, 12 Jan 2024 14:01:18 -0800 Subject: [PATCH 7/9] update licenses --- backend/third_party_licenses/apiserver.csv | 1 + backend/third_party_licenses/driver.csv | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/third_party_licenses/apiserver.csv b/backend/third_party_licenses/apiserver.csv index defbefb63ed..96936484fb8 100644 --- a/backend/third_party_licenses/apiserver.csv +++ b/backend/third_party_licenses/apiserver.csv @@ -61,6 +61,7 @@ github.com/klauspost/cpuid,https://github.com/klauspost/cpuid/blob/v1.3.1/LICENS github.com/klauspost/pgzip,https://github.com/klauspost/pgzip/blob/v1.2.5/LICENSE,MIT github.com/kubeflow/pipelines/api/v2alpha1/go,https://github.com/kubeflow/pipelines/blob/758c91f76784/api/LICENSE,Apache-2.0 github.com/kubeflow/pipelines/backend,https://github.com/kubeflow/pipelines/blob/HEAD/LICENSE,Apache-2.0 +github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform,https://github.com/kubeflow/pipelines/blob/aac4408237df/kubernetes_platform/LICENSE,Apache-2.0 github.com/kubeflow/pipelines/third_party/ml-metadata/go/ml_metadata,https://github.com/kubeflow/pipelines/blob/e1f0c010f800/third_party/ml-metadata/LICENSE,Apache-2.0 github.com/lann/builder,https://github.com/lann/builder/blob/47ae307949d0/LICENSE,MIT github.com/lann/ps,https://github.com/lann/ps/blob/62de8c46ede0/LICENSE,MIT diff --git a/backend/third_party_licenses/driver.csv b/backend/third_party_licenses/driver.csv index b05a884c4c2..5adb889df2b 100644 --- a/backend/third_party_licenses/driver.csv +++ b/backend/third_party_licenses/driver.csv @@ -31,7 +31,7 @@ github.com/josharian/intern,https://github.com/josharian/intern/blob/v1.0.0/lice github.com/json-iterator/go,https://github.com/json-iterator/go/blob/v1.1.12/LICENSE,MIT github.com/kubeflow/pipelines/api/v2alpha1/go,https://github.com/kubeflow/pipelines/blob/758c91f76784/api/LICENSE,Apache-2.0 github.com/kubeflow/pipelines/backend,https://github.com/kubeflow/pipelines/blob/HEAD/LICENSE,Apache-2.0 -github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform,https://github.com/kubeflow/pipelines/blob/bd9f74e34de6/kubernetes_platform/LICENSE,Apache-2.0 +github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform,https://github.com/kubeflow/pipelines/blob/aac4408237df/kubernetes_platform/LICENSE,Apache-2.0 github.com/kubeflow/pipelines/third_party/ml-metadata/go/ml_metadata,https://github.com/kubeflow/pipelines/blob/e1f0c010f800/third_party/ml-metadata/LICENSE,Apache-2.0 github.com/mailru/easyjson,https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE,MIT github.com/modern-go/concurrent,https://github.com/modern-go/concurrent/blob/bacd9c7ef1dd/LICENSE,Apache-2.0 From 53c80cda416ace1e84f0dfd9ee4dbf2d7166476b Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Thu, 25 Jan 2024 10:58:43 -0800 Subject: [PATCH 8/9] address comments --- .../src/v2/compiler/argocompiler/container.go | 14 ++++---- .../compiler/argocompiler/container_test.go | 29 ++++++++++++++++ .../python/test/unit/test_pod_metadata.py | 34 +++++++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/backend/src/v2/compiler/argocompiler/container.go b/backend/src/v2/compiler/argocompiler/container.go index d187202ad7a..f09241468ad 100644 --- a/backend/src/v2/compiler/argocompiler/container.go +++ b/backend/src/v2/compiler/argocompiler/container.go @@ -298,18 +298,20 @@ func extendPodMetadata( ) { // Get pod metadata information if kubernetesExecutorConfig.GetPodMetadata() != nil { - if kubernetesExecutorConfig.GetPodMetadata().GetLabels() != nil { + labels := kubernetesExecutorConfig.GetPodMetadata().GetLabels() + if labels != nil { if podMetadata.Labels == nil { - podMetadata.Labels = kubernetesExecutorConfig.GetPodMetadata().GetLabels() + podMetadata.Labels = labels } else { - podMetadata.Labels = extendMetadataMap(podMetadata.Labels, kubernetesExecutorConfig.GetPodMetadata().GetLabels()) + podMetadata.Labels = extendMetadataMap(podMetadata.Labels, labels) } } - if kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() != nil { + annotations := kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() + if annotations != nil { if podMetadata.Annotations == nil { - podMetadata.Annotations = kubernetesExecutorConfig.GetPodMetadata().GetAnnotations() + podMetadata.Annotations = annotations } else { - podMetadata.Annotations = extendMetadataMap(podMetadata.Annotations, kubernetesExecutorConfig.GetPodMetadata().GetAnnotations()) + podMetadata.Annotations = extendMetadataMap(podMetadata.Annotations, annotations) } } } diff --git a/backend/src/v2/compiler/argocompiler/container_test.go b/backend/src/v2/compiler/argocompiler/container_test.go index 5d5744bfede..f242d87a188 100644 --- a/backend/src/v2/compiler/argocompiler/container_test.go +++ b/backend/src/v2/compiler/argocompiler/container_test.go @@ -51,6 +51,35 @@ func Test_extendPodMetadata(t *testing.T) { }, }, }, + { + "Valid - try overwrite default pod labels and annotations", + &wfapi.Metadata{ + Annotations: map[string]string{ + "run_id": "654321", + }, + Labels: map[string]string{ + "kubeflow.com/kfp": "default-node", + }, + }, + &kubernetesplatform.KubernetesExecutorConfig{ + PodMetadata: &kubernetesplatform.PodMetadata{ + Annotations: map[string]string{ + "run_id": "123456", + }, + Labels: map[string]string{ + "kubeflow.com/kfp": "pipeline-node", + }, + }, + }, + &wfapi.Metadata{ + Annotations: map[string]string{ + "run_id": "654321", + }, + Labels: map[string]string{ + "kubeflow.com/kfp": "default-node", + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/kubernetes_platform/python/test/unit/test_pod_metadata.py b/kubernetes_platform/python/test/unit/test_pod_metadata.py index 7ea03d066c6..1bb3c5ab5cd 100644 --- a/kubernetes_platform/python/test/unit/test_pod_metadata.py +++ b/kubernetes_platform/python/test/unit/test_pod_metadata.py @@ -48,6 +48,40 @@ def my_pipeline(): } } + def test_add_same_one(self): + + @dsl.pipeline + def my_pipeline(): + task = comp() + kubernetes.add_pod_label( + task, + label_key='kubeflow.com/kfp', + label_value='pipeline-node', + ) + kubernetes.add_pod_label( + task, + label_key='kubeflow.com/kfp', + label_value='pipeline-node2', + ) + + assert json_format.MessageToDict(my_pipeline.platform_spec) == { + 'platforms': { + 'kubernetes': { + 'deploymentSpec': { + 'executors': { + 'exec-comp': { + 'podMetadata': { + 'labels': { + 'kubeflow.com/kfp': 'pipeline-node2' + } + } + } + } + } + } + } + } + def test_add_two_and_mix(self): @dsl.pipeline From 320d87b6802e86c7710eec4649ca84d2c8abe224 Mon Sep 17 00:00:00 2001 From: Tommy Li Date: Fri, 9 Feb 2024 09:09:12 -0800 Subject: [PATCH 9/9] update kubernetes_platform package to include the latest spec --- backend/third_party_licenses/apiserver.csv | 2 +- backend/third_party_licenses/driver.csv | 2 +- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/third_party_licenses/apiserver.csv b/backend/third_party_licenses/apiserver.csv index 96936484fb8..fc0d0eccced 100644 --- a/backend/third_party_licenses/apiserver.csv +++ b/backend/third_party_licenses/apiserver.csv @@ -61,7 +61,7 @@ github.com/klauspost/cpuid,https://github.com/klauspost/cpuid/blob/v1.3.1/LICENS github.com/klauspost/pgzip,https://github.com/klauspost/pgzip/blob/v1.2.5/LICENSE,MIT github.com/kubeflow/pipelines/api/v2alpha1/go,https://github.com/kubeflow/pipelines/blob/758c91f76784/api/LICENSE,Apache-2.0 github.com/kubeflow/pipelines/backend,https://github.com/kubeflow/pipelines/blob/HEAD/LICENSE,Apache-2.0 -github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform,https://github.com/kubeflow/pipelines/blob/aac4408237df/kubernetes_platform/LICENSE,Apache-2.0 +github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform,https://github.com/kubeflow/pipelines/blob/f51dc39614e4/kubernetes_platform/LICENSE,Apache-2.0 github.com/kubeflow/pipelines/third_party/ml-metadata/go/ml_metadata,https://github.com/kubeflow/pipelines/blob/e1f0c010f800/third_party/ml-metadata/LICENSE,Apache-2.0 github.com/lann/builder,https://github.com/lann/builder/blob/47ae307949d0/LICENSE,MIT github.com/lann/ps,https://github.com/lann/ps/blob/62de8c46ede0/LICENSE,MIT diff --git a/backend/third_party_licenses/driver.csv b/backend/third_party_licenses/driver.csv index 5adb889df2b..9880cb0254b 100644 --- a/backend/third_party_licenses/driver.csv +++ b/backend/third_party_licenses/driver.csv @@ -31,7 +31,7 @@ github.com/josharian/intern,https://github.com/josharian/intern/blob/v1.0.0/lice github.com/json-iterator/go,https://github.com/json-iterator/go/blob/v1.1.12/LICENSE,MIT github.com/kubeflow/pipelines/api/v2alpha1/go,https://github.com/kubeflow/pipelines/blob/758c91f76784/api/LICENSE,Apache-2.0 github.com/kubeflow/pipelines/backend,https://github.com/kubeflow/pipelines/blob/HEAD/LICENSE,Apache-2.0 -github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform,https://github.com/kubeflow/pipelines/blob/aac4408237df/kubernetes_platform/LICENSE,Apache-2.0 +github.com/kubeflow/pipelines/kubernetes_platform/go/kubernetesplatform,https://github.com/kubeflow/pipelines/blob/f51dc39614e4/kubernetes_platform/LICENSE,Apache-2.0 github.com/kubeflow/pipelines/third_party/ml-metadata/go/ml_metadata,https://github.com/kubeflow/pipelines/blob/e1f0c010f800/third_party/ml-metadata/LICENSE,Apache-2.0 github.com/mailru/easyjson,https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE,MIT github.com/modern-go/concurrent,https://github.com/modern-go/concurrent/blob/bacd9c7ef1dd/LICENSE,Apache-2.0 diff --git a/go.mod b/go.mod index 2c21b3904ff..b5ab01fd94b 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.4 // indirect github.com/kubeflow/pipelines/api v0.0.0-20230331215358-758c91f76784 - github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240111221413-aac4408237df + github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240207171236-f51dc39614e4 github.com/kubeflow/pipelines/third_party/ml-metadata v0.0.0-20230810215105-e1f0c010f800 github.com/lestrrat-go/strftime v1.0.4 github.com/mattn/go-sqlite3 v1.14.16 diff --git a/go.sum b/go.sum index 7e06319d151..9fcebdf3c77 100644 --- a/go.sum +++ b/go.sum @@ -936,8 +936,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/ktrysmt/go-bitbucket v0.9.32/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno= github.com/kubeflow/pipelines/api v0.0.0-20230331215358-758c91f76784 h1:ZVCoqnKnC2vctD7AqAHbWf05qw15VO5XSxCqkjObwtw= github.com/kubeflow/pipelines/api v0.0.0-20230331215358-758c91f76784/go.mod h1:T7TOQB36gGe97yUdfVAnYK5uuT0+uQbLNHDUHxYkmE4= -github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240111221413-aac4408237df h1:hskr5e/bAKNi8Bc15lG9uZ28q36v/y8qbKkDDix9NPo= -github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240111221413-aac4408237df/go.mod h1:CJkKr356RlpZP/gQRuHf3Myrn1qJtoUVe4EMCmtwarg= +github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240207171236-f51dc39614e4 h1:4WGf/JTH2Pks3A1fru2lk2u8gO/MR3g7tPJC7OXhAzk= +github.com/kubeflow/pipelines/kubernetes_platform v0.0.0-20240207171236-f51dc39614e4/go.mod h1:CJkKr356RlpZP/gQRuHf3Myrn1qJtoUVe4EMCmtwarg= github.com/kubeflow/pipelines/third_party/ml-metadata v0.0.0-20230810215105-e1f0c010f800 h1:YAW+X9xCW8Yq5tQaBBQaLTNU9CJj8Nr7lx1+k66ZHJ0= github.com/kubeflow/pipelines/third_party/ml-metadata v0.0.0-20230810215105-e1f0c010f800/go.mod h1:chIDffBaVQ/asNl1pTTdbAymYcuBKf8BR3YtSP+3FEU= github.com/labstack/echo v3.2.1+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=