From f2cb7927c1a1bd14d62258ba4e6a90257cdba74e Mon Sep 17 00:00:00 2001 From: Kristine Kunapuli Date: Tue, 17 Sep 2024 12:37:54 -0400 Subject: [PATCH 1/2] save --- harness/determined/common/api/bindings.py | 40 ++- master/internal/command/command.go | 1 + .../internal/command/command_job_service.go | 23 +- .../postgres_task_config_policy.go | 36 +++ master/internal/configpolicy/utils.go | 33 +++ master/internal/job/jobservice/jobservice.go | 4 + .../rm/agentrm/agent_resource_manager.go | 10 + .../dispatcher_resource_manager.go | 10 + .../kubernetes_resource_manager.go | 10 + master/internal/rm/resource_manager_iface.go | 14 ++ proto/pkg/apiv1/api.pb.go | 237 +++++++++--------- proto/pkg/apiv1/api.pb.gw.go | 34 ++- proto/src/determined/api/v1/api.proto | 1 + webui/react/src/services/api-ts-sdk/api.ts | 44 +++- 14 files changed, 352 insertions(+), 145 deletions(-) diff --git a/harness/determined/common/api/bindings.py b/harness/determined/common/api/bindings.py index cd0f6abd3f5..5c8ba14fbfd 100644 --- a/harness/determined/common/api/bindings.py +++ b/harness/determined/common/api/bindings.py @@ -12226,6 +12226,43 @@ def to_json(self, omit_unset: bool = False) -> typing.Dict[str, typing.Any]: } return out +class v1PutGlobalConfigPoliciesRequest(Printable): + """PutGlobalConfigPoliciesRequest sets global config + policies for the workload type. + """ + configPolicies: "typing.Optional[str]" = None + workloadType: "typing.Optional[str]" = None + + def __init__( + self, + *, + configPolicies: "typing.Union[str, None, Unset]" = _unset, + workloadType: "typing.Union[str, None, Unset]" = _unset, + ): + if not isinstance(configPolicies, Unset): + self.configPolicies = configPolicies + if not isinstance(workloadType, Unset): + self.workloadType = workloadType + + @classmethod + def from_json(cls, obj: Json) -> "v1PutGlobalConfigPoliciesRequest": + kwargs: "typing.Dict[str, typing.Any]" = { + } + if "configPolicies" in obj: + kwargs["configPolicies"] = obj["configPolicies"] + if "workloadType" in obj: + kwargs["workloadType"] = obj["workloadType"] + return cls(**kwargs) + + def to_json(self, omit_unset: bool = False) -> typing.Dict[str, typing.Any]: + out: "typing.Dict[str, typing.Any]" = { + } + if not omit_unset or "configPolicies" in vars(self): + out["configPolicies"] = self.configPolicies + if not omit_unset or "workloadType" in vars(self): + out["workloadType"] = self.workloadType + return out + class v1PutGlobalConfigPoliciesResponse(Printable): """Response to PutGlobalConfigPoliciesRequest.""" configPolicies: "typing.Optional[typing.Dict[str, typing.Any]]" = None @@ -23751,6 +23788,7 @@ def put_PutExperimentsRetainLogs( def put_PutGlobalConfigPolicies( session: "api.BaseSession", *, + body: "v1PutGlobalConfigPoliciesRequest", workloadType: str, ) -> "v1PutGlobalConfigPoliciesResponse": """Add or update global task config policies. @@ -23764,7 +23802,7 @@ def put_PutGlobalConfigPolicies( method="PUT", path=f"/api/v1/config-policies/global/{workloadType}", params=_params, - json=None, + json=body.to_json(True), data=None, headers=None, timeout=None, diff --git a/master/internal/command/command.go b/master/internal/command/command.go index f21dd0035f6..13a9596c585 100644 --- a/master/internal/command/command.go +++ b/master/internal/command/command.go @@ -277,6 +277,7 @@ func (c *Command) garbageCollect() { go DefaultCmdService.unregisterCommand(c.taskID) } +// TODO update me to include constraints func (c *Command) setNTSCPriority(priority int, forward bool) error { if forward { switch err := c.rm.SetGroupPriority(sproto.SetGroupPriority{ diff --git a/master/internal/command/command_job_service.go b/master/internal/command/command_job_service.go index 92ad1850075..9fc8c41994f 100644 --- a/master/internal/command/command_job_service.go +++ b/master/internal/command/command_job_service.go @@ -1,13 +1,16 @@ package command import ( + "context" "fmt" "google.golang.org/protobuf/types/known/timestamppb" "github.com/determined-ai/determined/master/internal/config" + "github.com/determined-ai/determined/master/internal/configpolicy" "github.com/determined-ai/determined/master/internal/rm/rmerrors" "github.com/determined-ai/determined/master/internal/sproto" + "github.com/determined-ai/determined/master/pkg/model" "github.com/determined-ai/determined/proto/pkg/jobv1" ) @@ -47,7 +50,25 @@ func (c *Command) SetJobPriority(priority int) error { if priority < 1 || priority > 99 { return fmt.Errorf("priority must be between 1 and 99") } - err := c.setNTSCPriority(priority, true) + + // check if a priority limit has been set in task config policies + // TODO create an appropriate context with a timeout + //scope := + //limit, found, err := configpolicy.GetPriorityLimit(context.TODO(), ) + wkspID := int(c.GenericCommandSpec.Metadata.WorkspaceID) + priorityLimit, found, err := configpolicy.GetPriorityLimitPrecedence(context.TODO(), wkspID, model.NTSCType) + if found { + + ok := configpolicy.PriorityOK(priority, priorityLimit, c.rm) + if !ok { + return fmt.Errorf("priority exceeds task config policy's priority_limit: %d", priorityLimit) + } + + } else if err != nil { + return err + } + + err = c.setNTSCPriority(priority, true) if err != nil { c.syslog.WithError(err).Info("setting command job priority") } diff --git a/master/internal/configpolicy/postgres_task_config_policy.go b/master/internal/configpolicy/postgres_task_config_policy.go index 2096cf62a2d..7d513f25437 100644 --- a/master/internal/configpolicy/postgres_task_config_policy.go +++ b/master/internal/configpolicy/postgres_task_config_policy.go @@ -2,6 +2,7 @@ package configpolicy import ( "context" + "database/sql" "fmt" "strings" @@ -88,6 +89,41 @@ func GetNTSCConfigPolicies(ctx context.Context, return &ntscTCP, nil } +// GetPriorityLimit reads the priority limit for the given scope and workload type. It returns found=false if no limit exists. +func GetPriorityLimit(ctx context.Context, scope *int, workloadType string) (limit int, found bool, err error) { + + if !ValidWorkloadType(workloadType) { + return 0, false, fmt.Errorf("invalid workload type: %s", workloadType) + } + + // FIXME query jsonb directly + // FIXME do more sophisticated coalesce and jsbonb query to optimize (CLI to postgres12) + wkspQuery := wkspIDQuery + if scope == nil { + wkspQuery = wkspIDGlobalQuery + } + + var constraints *model.Constraints + err = db.Bun().NewSelect(). + Table("task_config_policies"). + Column("constraints"). + Where(wkspQuery, scope). + Where("workload_type = ?", workloadType). + Scan(ctx, constraints) + + if err == sql.ErrNoRows { + return 0, false, nil + } else if err != nil { + return 0, false, fmt.Errorf("error retrieving priority limit: %w", err) + } + + if constraints != nil && constraints.PriorityLimit != nil { + return *constraints.PriorityLimit, true, nil + } + + return 0, false, nil +} + // DeleteConfigPolicies deletes the invariant experiment config and constraints for the // given scope (global or workspace-level) and workload type. func DeleteConfigPolicies(ctx context.Context, diff --git a/master/internal/configpolicy/utils.go b/master/internal/configpolicy/utils.go index 0ab9dc07a1b..9b240487a52 100644 --- a/master/internal/configpolicy/utils.go +++ b/master/internal/configpolicy/utils.go @@ -2,12 +2,14 @@ package configpolicy import ( "bytes" + "context" "encoding/json" "fmt" "github.com/ghodss/yaml" "google.golang.org/protobuf/types/known/structpb" + "github.com/determined-ai/determined/master/internal/rm" "github.com/determined-ai/determined/master/pkg/model" "github.com/determined-ai/determined/master/pkg/protoutils" ) @@ -22,6 +24,37 @@ func ValidWorkloadType(val string) bool { } } +// GetPriorityLimitPrecedence retrieves the priority limit using order of precedence +func GetPriorityLimitPrecedence(ctx context.Context, workspace_id int, workload_type string) (limit int, found bool, err error) { + // highest precedence: get global limit + if limit, found, err = GetPriorityLimit(ctx, nil, workload_type); found { + return limit, found, err + } + + // second precedence: get workspace limit + if limit, found, err = GetPriorityLimit(ctx, &workspace_id, workload_type); found { + return limit, found, err + } + + // default + return 0, false, nil +} + +// PriorityLimit returns the ne +func PriorityOK(currPriority int, priorityLimit int, resourceManager rm.ResourceManager) bool { + smallerHigher, err := resourceManager.SmallerValueIsHigherPriority() + if err != nil { + // RM does not have the concept of priority. No Limit applied. + return true + } + + if smallerHigher { + return currPriority >= priorityLimit + } + + return currPriority <= priorityLimit +} + // UnmarshalExperimentConfigPolicy unpacks a string into ExperimentConfigPolicy struct. func UnmarshalExperimentConfigPolicy(str string) (*ExperimentConfigPolicies, error) { var expConfigPolicy ExperimentConfigPolicies diff --git a/master/internal/job/jobservice/jobservice.go b/master/internal/job/jobservice/jobservice.go index e0f7864a214..7666811fcb9 100644 --- a/master/internal/job/jobservice/jobservice.go +++ b/master/internal/job/jobservice/jobservice.go @@ -189,7 +189,11 @@ func (s *Service) applyUpdate(update *jobv1.QueueControl) error { switch action := update.GetAction().(type) { case *jobv1.QueueControl_Priority: + // TODO handle priority updates with new constraints priority := int(action.Priority) + // FIXME add rm as an argument? InternalExperimnt seems to have rm in it. What about workspace? + // TaskSpec seems to have workspace saved as a string + //wkspID := return j.SetJobPriority(priority) case *jobv1.QueueControl_Weight: if action.Weight <= 0 { diff --git a/master/internal/rm/agentrm/agent_resource_manager.go b/master/internal/rm/agentrm/agent_resource_manager.go index c2e3cd14dc7..7f31db3b686 100644 --- a/master/internal/rm/agentrm/agent_resource_manager.go +++ b/master/internal/rm/agentrm/agent_resource_manager.go @@ -108,6 +108,16 @@ func newAgentResourceManager( return a, nil } +// Type implements rm.ResourceManager. +func (a *ResourceManager) Type() string { + return rm.AgentRM +} + +// SmallerValueIsHigherPriority returns true if smaller priority values indicate a higher priority level. +func (a *ResourceManager) SmallerValueIsHigherPriority() (bool, error) { + return true, nil +} + // Allocate implements rm.ResourceManager. func (a *ResourceManager) Allocate(msg sproto.AllocateRequest) (*sproto.ResourcesSubscription, error) { // this code exists to handle the case where an experiment does not have diff --git a/master/internal/rm/dispatcherrm/dispatcher_resource_manager.go b/master/internal/rm/dispatcherrm/dispatcher_resource_manager.go index fe82a0aaeb2..a9d8bd1cf30 100644 --- a/master/internal/rm/dispatcherrm/dispatcher_resource_manager.go +++ b/master/internal/rm/dispatcherrm/dispatcher_resource_manager.go @@ -206,6 +206,16 @@ func New( return m, nil } +// Type implements rm.ResourceManager. +func (m *DispatcherResourceManager) Type() string { + return rm.SlurmType +} + +// SmallerValueIsHigherPriority returns true if smaller priority values indicate a higher priority level. +func (m *DispatcherResourceManager) SmallerValueIsHigherPriority() (bool, error) { + return false, fmt.Errorf("priority not implemented") +} + // Allocate adds a task to the queue to be allocated. func (m *DispatcherResourceManager) Allocate(msg sproto.AllocateRequest) (*sproto.ResourcesSubscription, error) { m.mu.Lock() diff --git a/master/internal/rm/kubernetesrm/kubernetes_resource_manager.go b/master/internal/rm/kubernetesrm/kubernetes_resource_manager.go index 9ec6065dd66..1e682306bc5 100644 --- a/master/internal/rm/kubernetesrm/kubernetes_resource_manager.go +++ b/master/internal/rm/kubernetesrm/kubernetes_resource_manager.go @@ -142,6 +142,16 @@ func New( return k, nil } +// Type implements rm.ResourceManager. +func (k *ResourceManager) Type() string { + return rm.KubernetesType +} + +// SmallerValueIsHigherPriority returns true if smaller priority values indicate a higher priority level. +func (k *ResourceManager) SmallerValueIsHigherPriority() (bool, error) { + return false, nil +} + // Allocate implements rm.ResourceManager. func (k *ResourceManager) Allocate(msg sproto.AllocateRequest) (*sproto.ResourcesSubscription, error) { // This code exists to handle the case where an experiment does not have diff --git a/master/internal/rm/resource_manager_iface.go b/master/internal/rm/resource_manager_iface.go index 5bcb8bbd618..b7f972da24d 100644 --- a/master/internal/rm/resource_manager_iface.go +++ b/master/internal/rm/resource_manager_iface.go @@ -10,6 +10,18 @@ import ( "github.com/determined-ai/determined/proto/pkg/jobv1" ) +// Resource Manager types. +const ( + // Agent Resource Manager constant. + AgentRM string = "AGENT" + // Kubernetes Resource Manager constant. + KubernetesType string = "KUBERNETES" + // Multi RM constant. + MultiType string = "MultiRM" + // Slurm Resource Manager constant. + SlurmType string = "SLURM" +) + // ResourceManager is an interface for a resource manager, which can allocate and manage resources. type ResourceManager interface { // Basic functionality @@ -19,6 +31,8 @@ type ResourceManager interface { ValidateResources(sproto.ValidateResourcesRequest) ([]command.LaunchWarning, error) DeleteJob(sproto.DeleteJob) (sproto.DeleteJobResponse, error) NotifyContainerRunning(sproto.NotifyContainerRunning) error + SmallerValueIsHigherPriority() (bool, error) + Type() string // Scheduling related stuff SetGroupMaxSlots(sproto.SetGroupMaxSlots) diff --git a/proto/pkg/apiv1/api.pb.go b/proto/pkg/apiv1/api.pb.go index b2a18678194..64c6f23d20c 100644 --- a/proto/pkg/apiv1/api.pb.go +++ b/proto/pkg/apiv1/api.pb.go @@ -81,7 +81,7 @@ var file_determined_api_v1_api_proto_rawDesc = []byte{ 0x61, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x70, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, - 0x88, 0xde, 0x02, 0x0a, 0x0a, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x12, + 0x8b, 0xde, 0x02, 0x0a, 0x0a, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x7e, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1f, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x64, 0x65, 0x74, 0x65, @@ -2815,7 +2815,7 @@ var file_determined_api_v1_api_proto_rawDesc = []byte{ 0x69, 0x67, 0x2d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0xc2, 0x01, 0x0a, 0x17, 0x50, 0x75, 0x74, + 0x74, 0x79, 0x70, 0x65, 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0xc5, 0x01, 0x0a, 0x17, 0x50, 0x75, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x47, 0x6c, 0x6f, 0x62, @@ -2823,127 +2823,128 @@ var file_determined_api_v1_api_proto_rawDesc = []byte{ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x92, 0x41, 0x07, - 0x0a, 0x05, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x1a, 0x2e, 0x2f, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x43, 0x92, 0x41, 0x07, + 0x0a, 0x05, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x1a, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2f, 0x7b, 0x77, - 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, 0x12, 0xde, 0x01, - 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x34, 0x2e, 0x64, - 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x92, 0x41, 0x07, 0x0a, 0x05, - 0x41, 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x12, 0x41, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x65, 0x73, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, - 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x7b, - 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, 0x12, 0xc2, - 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x64, 0x65, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, 0x3a, 0x01, 0x2a, + 0x12, 0xde, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, + 0x34, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x92, 0x41, + 0x07, 0x0a, 0x05, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x12, 0x41, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x73, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x7d, 0x12, 0xc2, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x40, 0x92, 0x41, 0x07, 0x0a, 0x05, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x2d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x67, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x7d, 0x12, 0xe7, 0x01, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x37, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x32, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x92, 0x41, 0x07, 0x0a, 0x05, 0x41, 0x6c, 0x70, 0x68, 0x61, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, + 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, 0x12, 0xe7, 0x01, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x37, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, + 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x38, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x92, 0x41, 0x07, + 0x0a, 0x05, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x2a, 0x41, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x73, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, + 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, + 0x12, 0xcb, 0x01, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, + 0x34, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, - 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x92, 0x41, 0x07, 0x0a, 0x05, 0x41, - 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x2a, 0x41, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x69, 0x65, 0x73, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2f, 0x7b, - 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x7b, 0x77, - 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, 0x12, 0xcb, 0x01, - 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x34, 0x2e, 0x64, - 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x92, 0x41, 0x07, 0x0a, 0x05, - 0x41, 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x2a, 0x2e, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x65, 0x73, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2f, 0x7b, 0x77, 0x6f, 0x72, - 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, 0x42, 0xda, 0x07, 0x5a, 0x33, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2d, 0x61, 0x69, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, - 0x69, 0x76, 0x31, 0x92, 0x41, 0xa1, 0x07, 0x12, 0x95, 0x06, 0x0a, 0x15, 0x44, 0x65, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x41, 0x50, 0x49, 0x20, 0x28, 0x42, 0x65, 0x74, 0x61, - 0x29, 0x12, 0xf5, 0x04, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x68, - 0x65, 0x6c, 0x70, 0x73, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x20, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, - 0x6c, 0x79, 0x2c, 0x20, 0x65, 0x61, 0x73, 0x69, 0x6c, 0x79, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, - 0x20, 0x47, 0x50, 0x55, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2c, 0x20, - 0x61, 0x6e, 0x64, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, - 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x44, 0x65, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x64, - 0x65, 0x65, 0x70, 0x20, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x67, - 0x69, 0x6e, 0x65, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, - 0x6f, 0x6e, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, - 0x74, 0x72, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x20, - 0x61, 0x74, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, - 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x6f, 0x72, - 0x72, 0x79, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x44, 0x65, 0x76, 0x4f, 0x70, 0x73, 0x20, - 0x6f, 0x72, 0x20, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x75, 0x73, 0x74, 0x6f, - 0x6d, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x20, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x72, 0x20, - 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x72, 0x61, 0x63, 0x6b, - 0x69, 0x6e, 0x67, 0x2e, 0x0a, 0x0a, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x68, - 0x69, 0x6e, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, - 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x20, - 0x74, 0x68, 0x61, 0x74, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x67, 0x61, 0x70, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x6f, - 0x6c, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x54, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x46, 0x6c, - 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x50, 0x79, 0x54, 0x6f, 0x72, 0x63, 0x68, 0x20, 0x2d, - 0x2d, 0x2d, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x67, 0x72, - 0x65, 0x61, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, - 0x20, 0x72, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, - 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x47, 0x50, 0x55, 0x20, 0x2d, 0x2d, - 0x2d, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, - 0x67, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x69, 0x73, 0x65, 0x20, 0x77, - 0x68, 0x65, 0x6e, 0x20, 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x6c, - 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x74, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, - 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, - 0x65, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, - 0x20, 0x69, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2e, 0x22, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x41, 0x49, 0x12, 0x16, 0x68, 0x74, 0x74, 0x70, - 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, - 0x69, 0x2f, 0x1a, 0x17, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x40, 0x64, 0x65, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x69, 0x2a, 0x3d, 0x0a, 0x0a, 0x41, - 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x32, 0x2e, 0x30, 0x12, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x3a, - 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6f, 0x72, 0x67, - 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x2f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, - 0x45, 0x2d, 0x32, 0x2e, 0x30, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x32, 0x03, 0x30, 0x2e, 0x31, 0x2a, - 0x02, 0x01, 0x02, 0x5a, 0x4a, 0x0a, 0x48, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x39, 0x08, 0x02, 0x12, 0x24, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, - 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x1a, 0x0d, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x02, 0x62, - 0x11, 0x0a, 0x0f, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x12, 0x00, 0x72, 0x24, 0x0a, 0x1b, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, - 0x20, 0x41, 0x49, 0x20, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x05, 0x2f, 0x64, 0x6f, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x92, 0x41, + 0x07, 0x0a, 0x05, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x2a, 0x2e, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2d, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2f, 0x7b, + 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, 0x42, 0xda, + 0x07, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2d, 0x61, 0x69, 0x2f, 0x64, 0x65, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x6b, 0x67, + 0x2f, 0x61, 0x70, 0x69, 0x76, 0x31, 0x92, 0x41, 0xa1, 0x07, 0x12, 0x95, 0x06, 0x0a, 0x15, 0x44, + 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x41, 0x50, 0x49, 0x20, 0x28, 0x42, + 0x65, 0x74, 0x61, 0x29, 0x12, 0xf5, 0x04, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, + 0x64, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x73, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x6c, 0x65, 0x61, + 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, + 0x6e, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x71, 0x75, + 0x69, 0x63, 0x6b, 0x6c, 0x79, 0x2c, 0x20, 0x65, 0x61, 0x73, 0x69, 0x6c, 0x79, 0x20, 0x73, 0x68, + 0x61, 0x72, 0x65, 0x20, 0x47, 0x50, 0x55, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x6c, 0x79, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x2e, 0x20, + 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x73, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, + 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6f, 0x63, + 0x75, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x73, 0x20, 0x61, 0x74, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2c, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x6f, 0x75, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, + 0x77, 0x6f, 0x72, 0x72, 0x79, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x44, 0x65, 0x76, 0x4f, + 0x70, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x20, + 0x6f, 0x72, 0x20, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x72, + 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x0a, 0x0a, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, + 0x20, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x70, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, + 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x54, 0x65, 0x6e, 0x73, 0x6f, + 0x72, 0x46, 0x6c, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x50, 0x79, 0x54, 0x6f, 0x72, 0x63, + 0x68, 0x20, 0x2d, 0x2d, 0x2d, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x6f, 0x72, 0x6b, + 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, + 0x67, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x47, 0x50, 0x55, + 0x20, 0x2d, 0x2d, 0x2d, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6c, + 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x69, 0x73, + 0x65, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x65, + 0x70, 0x20, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x74, 0x20, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x74, + 0x61, 0x20, 0x73, 0x65, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, + 0x61, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2e, 0x22, 0x40, 0x0a, 0x0d, + 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x41, 0x49, 0x12, 0x16, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, + 0x64, 0x2e, 0x61, 0x69, 0x2f, 0x1a, 0x17, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, + 0x40, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x61, 0x69, 0x2a, 0x3d, + 0x0a, 0x0a, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x32, 0x2e, 0x30, 0x12, 0x2f, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, + 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x2f, 0x4c, 0x49, 0x43, + 0x45, 0x4e, 0x53, 0x45, 0x2d, 0x32, 0x2e, 0x30, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x32, 0x03, 0x30, + 0x2e, 0x31, 0x2a, 0x02, 0x01, 0x02, 0x5a, 0x4a, 0x0a, 0x48, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x72, + 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x39, 0x08, 0x02, 0x12, 0x24, 0x42, 0x65, 0x61, + 0x72, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x1a, 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x02, 0x62, 0x11, 0x0a, 0x0f, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x12, 0x00, 0x72, 0x24, 0x0a, 0x1b, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, + 0x6e, 0x65, 0x64, 0x20, 0x41, 0x49, 0x20, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x05, 0x2f, 0x64, 0x6f, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var file_determined_api_v1_api_proto_goTypes = []interface{}{ diff --git a/proto/pkg/apiv1/api.pb.gw.go b/proto/pkg/apiv1/api.pb.gw.go index e42ba5f1bba..fb5c39e3f46 100644 --- a/proto/pkg/apiv1/api.pb.gw.go +++ b/proto/pkg/apiv1/api.pb.gw.go @@ -13333,14 +13333,18 @@ func local_request_Determined_PutWorkspaceConfigPolicies_0(ctx context.Context, } -var ( - filter_Determined_PutGlobalConfigPolicies_0 = &utilities.DoubleArray{Encoding: map[string]int{"workload_type": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} -) - func request_Determined_PutGlobalConfigPolicies_0(ctx context.Context, marshaler runtime.Marshaler, client DeterminedClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq PutGlobalConfigPoliciesRequest var metadata runtime.ServerMetadata + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + var ( val string ok bool @@ -13359,13 +13363,6 @@ func request_Determined_PutGlobalConfigPolicies_0(ctx context.Context, marshaler return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "workload_type", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Determined_PutGlobalConfigPolicies_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := client.PutGlobalConfigPolicies(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -13375,6 +13372,14 @@ func local_request_Determined_PutGlobalConfigPolicies_0(ctx context.Context, mar var protoReq PutGlobalConfigPoliciesRequest var metadata runtime.ServerMetadata + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + var ( val string ok bool @@ -13393,13 +13398,6 @@ func local_request_Determined_PutGlobalConfigPolicies_0(ctx context.Context, mar return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "workload_type", err) } - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Determined_PutGlobalConfigPolicies_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := server.PutGlobalConfigPolicies(ctx, &protoReq) return msg, metadata, err diff --git a/proto/src/determined/api/v1/api.proto b/proto/src/determined/api/v1/api.proto index 84dacd1bbe5..97bc488b248 100644 --- a/proto/src/determined/api/v1/api.proto +++ b/proto/src/determined/api/v1/api.proto @@ -2836,6 +2836,7 @@ service Determined { returns (PutGlobalConfigPoliciesResponse) { option (google.api.http) = { put: "/api/v1/config-policies/global/{workload_type}" + body: "*" }; option (grpc.gateway.protoc_gen_swagger.options.openapiv2_operation) = { tags: "Alpha" diff --git a/webui/react/src/services/api-ts-sdk/api.ts b/webui/react/src/services/api-ts-sdk/api.ts index dfce495eecf..c6fdab2896a 100644 --- a/webui/react/src/services/api-ts-sdk/api.ts +++ b/webui/react/src/services/api-ts-sdk/api.ts @@ -8893,6 +8893,25 @@ export interface V1PutExperimentsRetainLogsResponse { */ results: Array; } +/** + * PutGlobalConfigPoliciesRequest sets global config policies for the workload type. + * @export + * @interface V1PutGlobalConfigPoliciesRequest + */ +export interface V1PutGlobalConfigPoliciesRequest { + /** + * The workload type the config policies apply to: EXPERIMENT or NTSC. + * @type {string} + * @memberof V1PutGlobalConfigPoliciesRequest + */ + workloadType?: string; + /** + * The config policies to use. Contains both invariant configs and constraints in yaml or json format. + * @type {string} + * @memberof V1PutGlobalConfigPoliciesRequest + */ + configPolicies?: string; +} /** * Response to PutGlobalConfigPoliciesRequest. * @export @@ -12993,14 +13012,19 @@ export const AlphaApiFetchParamCreator = function (configuration?: Configuration * * @summary Add or update global task config policies. * @param {string} workloadType The workload type the config policies apply to: EXPERIMENT or NTSC. + * @param {V1PutGlobalConfigPoliciesRequest} body * @param {*} [options] Override http request option. * @throws {RequiredError} */ - putGlobalConfigPolicies(workloadType: string, options: any = {}): FetchArgs { + putGlobalConfigPolicies(workloadType: string, body: V1PutGlobalConfigPoliciesRequest, options: any = {}): FetchArgs { // verify required parameter 'workloadType' is not null or undefined if (workloadType === null || workloadType === undefined) { throw new RequiredError('workloadType','Required parameter workloadType was null or undefined when calling putGlobalConfigPolicies.'); } + // verify required parameter 'body' is not null or undefined + if (body === null || body === undefined) { + throw new RequiredError('body','Required parameter body was null or undefined when calling putGlobalConfigPolicies.'); + } const localVarPath = `/api/v1/config-policies/global/{workloadType}` .replace(`{${"workloadType"}}`, encodeURIComponent(String(workloadType))); const localVarUrlObj = new URL(localVarPath, BASE_PATH); @@ -13016,9 +13040,12 @@ export const AlphaApiFetchParamCreator = function (configuration?: Configuration localVarHeaderParameter["Authorization"] = localVarApiKeyValue; } + localVarHeaderParameter['Content-Type'] = 'application/json'; + objToSearchParams(localVarQueryParameter, localVarUrlObj.searchParams); objToSearchParams(options.query || {}, localVarUrlObj.searchParams); localVarRequestOptions.headers = { ...localVarHeaderParameter, ...options.headers }; + localVarRequestOptions.body = JSON.stringify(body) return { url: `${localVarUrlObj.pathname}${localVarUrlObj.search}`, @@ -13166,11 +13193,12 @@ export const AlphaApiFp = function (configuration?: Configuration) { * * @summary Add or update global task config policies. * @param {string} workloadType The workload type the config policies apply to: EXPERIMENT or NTSC. + * @param {V1PutGlobalConfigPoliciesRequest} body * @param {*} [options] Override http request option. * @throws {RequiredError} */ - putGlobalConfigPolicies(workloadType: string, options?: any): (fetch?: FetchAPI, basePath?: string) => Promise { - const localVarFetchArgs = AlphaApiFetchParamCreator(configuration).putGlobalConfigPolicies(workloadType, options); + putGlobalConfigPolicies(workloadType: string, body: V1PutGlobalConfigPoliciesRequest, options?: any): (fetch?: FetchAPI, basePath?: string) => Promise { + const localVarFetchArgs = AlphaApiFetchParamCreator(configuration).putGlobalConfigPolicies(workloadType, body, options); return (fetch: FetchAPI = window.fetch, basePath: string = BASE_PATH) => { return fetch(basePath + localVarFetchArgs.url, localVarFetchArgs.options).then((response) => { if (response.status >= 200 && response.status < 300) { @@ -13257,11 +13285,12 @@ export const AlphaApiFactory = function (configuration?: Configuration, fetch?: * * @summary Add or update global task config policies. * @param {string} workloadType The workload type the config policies apply to: EXPERIMENT or NTSC. + * @param {V1PutGlobalConfigPoliciesRequest} body * @param {*} [options] Override http request option. * @throws {RequiredError} */ - putGlobalConfigPolicies(workloadType: string, options?: any) { - return AlphaApiFp(configuration).putGlobalConfigPolicies(workloadType, options)(fetch, basePath); + putGlobalConfigPolicies(workloadType: string, body: V1PutGlobalConfigPoliciesRequest, options?: any) { + return AlphaApiFp(configuration).putGlobalConfigPolicies(workloadType, body, options)(fetch, basePath); }, /** * @@ -13339,12 +13368,13 @@ export class AlphaApi extends BaseAPI { * * @summary Add or update global task config policies. * @param {string} workloadType The workload type the config policies apply to: EXPERIMENT or NTSC. + * @param {V1PutGlobalConfigPoliciesRequest} body * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AlphaApi */ - public putGlobalConfigPolicies(workloadType: string, options?: any) { - return AlphaApiFp(this.configuration).putGlobalConfigPolicies(workloadType, options)(this.fetch, this.basePath) + public putGlobalConfigPolicies(workloadType: string, body: V1PutGlobalConfigPoliciesRequest, options?: any) { + return AlphaApiFp(this.configuration).putGlobalConfigPolicies(workloadType, body, options)(this.fetch, this.basePath) } /** From 691519e9f830e8401cc78ef9d9f4194d914837ea Mon Sep 17 00:00:00 2001 From: Kristine Kunapuli Date: Tue, 17 Sep 2024 16:09:19 -0400 Subject: [PATCH 2/2] mostly working - need updated db schema --- .../internal/command/command_job_service.go | 11 +- .../postgres_task_config_policy.go | 8 +- .../postgres_task_config_policy_intg_test.go | 109 ++++++++++++++++++ master/internal/configpolicy/utils.go | 12 +- .../internal/configpolicy/utils_intg_test.go | 92 +++++++++++++++ master/internal/configpolicy/utils_test.go | 26 +++++ master/internal/job/jobservice/jobservice.go | 4 - .../rm/agentrm/agent_resource_manager.go | 5 - .../dispatcher_resource_manager.go | 5 - .../kubernetes_resource_manager.go | 5 - master/internal/rm/multirm/multirm.go | 5 + master/internal/rm/resource_manager_iface.go | 13 --- 12 files changed, 244 insertions(+), 51 deletions(-) create mode 100644 master/internal/configpolicy/utils_intg_test.go diff --git a/master/internal/command/command_job_service.go b/master/internal/command/command_job_service.go index 9fc8c41994f..d26a3a42678 100644 --- a/master/internal/command/command_job_service.go +++ b/master/internal/command/command_job_service.go @@ -52,19 +52,20 @@ func (c *Command) SetJobPriority(priority int) error { } // check if a priority limit has been set in task config policies - // TODO create an appropriate context with a timeout - //scope := - //limit, found, err := configpolicy.GetPriorityLimit(context.TODO(), ) wkspID := int(c.GenericCommandSpec.Metadata.WorkspaceID) priorityLimit, found, err := configpolicy.GetPriorityLimitPrecedence(context.TODO(), wkspID, model.NTSCType) - if found { - ok := configpolicy.PriorityOK(priority, priorityLimit, c.rm) + // returns err if RM does not have concept of priority + smallerIsHigher, rmErr := c.rm.SmallerValueIsHigherPriority() + if found && rmErr == nil { + + ok := configpolicy.PriorityOK(priority, priorityLimit, smallerIsHigher) if !ok { return fmt.Errorf("priority exceeds task config policy's priority_limit: %d", priorityLimit) } } else if err != nil { + // TODO do we really want to block on this? return err } diff --git a/master/internal/configpolicy/postgres_task_config_policy.go b/master/internal/configpolicy/postgres_task_config_policy.go index 7d513f25437..e545119dd73 100644 --- a/master/internal/configpolicy/postgres_task_config_policy.go +++ b/master/internal/configpolicy/postgres_task_config_policy.go @@ -96,20 +96,18 @@ func GetPriorityLimit(ctx context.Context, scope *int, workloadType string) (lim return 0, false, fmt.Errorf("invalid workload type: %s", workloadType) } - // FIXME query jsonb directly - // FIXME do more sophisticated coalesce and jsbonb query to optimize (CLI to postgres12) wkspQuery := wkspIDQuery if scope == nil { wkspQuery = wkspIDGlobalQuery } - var constraints *model.Constraints + var constraints model.Constraints err = db.Bun().NewSelect(). Table("task_config_policies"). Column("constraints"). Where(wkspQuery, scope). Where("workload_type = ?", workloadType). - Scan(ctx, constraints) + Scan(ctx, &constraints) if err == sql.ErrNoRows { return 0, false, nil @@ -117,7 +115,7 @@ func GetPriorityLimit(ctx context.Context, scope *int, workloadType string) (lim return 0, false, fmt.Errorf("error retrieving priority limit: %w", err) } - if constraints != nil && constraints.PriorityLimit != nil { + if constraints.PriorityLimit != nil { return *constraints.PriorityLimit, true, nil } diff --git a/master/internal/configpolicy/postgres_task_config_policy_intg_test.go b/master/internal/configpolicy/postgres_task_config_policy_intg_test.go index 01d9dfbf37d..644efef0925 100644 --- a/master/internal/configpolicy/postgres_task_config_policy_intg_test.go +++ b/master/internal/configpolicy/postgres_task_config_policy_intg_test.go @@ -207,6 +207,115 @@ func TestSetNTSCConfigPolicies(t *testing.T) { require.ErrorContains(t, err, "violates foreign key constraint") } +func TestWorkspaceGetPriorityLimit(t *testing.T) { + ctx := context.Background() + require.NoError(t, etc.SetRootPath(db.RootFromDB)) + pgDB, cleanup := db.MustResolveNewPostgresDatabase(t) + defer cleanup() + db.MustMigrateTestPostgres(t, pgDB, db.MigrationsFromDB) + user := db.RequireMockUser(t, pgDB) + + // add a workspace to use + w := model.Workspace{Name: uuid.NewString(), UserID: user.ID} + _, err := db.Bun().NewInsert().Model(&w).Exec(ctx) + require.NoError(t, err) + defer func() { + err := db.CleanupMockWorkspace([]int32{int32(w.ID)}) + if err != nil { + log.Errorf("error when cleaning up mock workspaces") + } + }() + + // add priority limit for workspace NTSC + wkspLimit := 20 + wkspInput := model.NTSCTaskConfigPolicies{ + WorkloadType: model.NTSCType, + WorkspaceID: &w.ID, + Constraints: model.Constraints{ + PriorityLimit: &wkspLimit, + }, + LastUpdatedBy: user.ID, + } + err = SetNTSCConfigPolicies(ctx, &wkspInput) + require.NoError(t, err) + + // get priority limit; should match workspace + res, found, err := GetPriorityLimit(ctx, &w.ID, model.NTSCType) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, wkspLimit, res) + + // get limit for workspace that does not exist + wkspIDDoesNotExist := 404 + res, found, err = GetPriorityLimit(ctx, &wkspIDDoesNotExist, model.NTSCType) + require.NoError(t, err) + require.False(t, found) + + // read global + res, found, err = GetPriorityLimit(ctx, nil, model.NTSCType) + require.NoError(t, err) + require.False(t, found) + + // read experiment + res, found, err = GetPriorityLimit(ctx, &w.ID, model.ExperimentType) + require.NoError(t, err) + require.False(t, found) + + // read invalid workload type + res, found, err = GetPriorityLimit(ctx, &w.ID, "bogus") + require.Error(t, err) + require.False(t, found) +} + +func TestGlobalGetPriorityLimit(t *testing.T) { + ctx := context.Background() + require.NoError(t, etc.SetRootPath(db.RootFromDB)) + pgDB, cleanup := db.MustResolveNewPostgresDatabase(t) + defer cleanup() + db.MustMigrateTestPostgres(t, pgDB, db.MigrationsFromDB) + user := db.RequireMockUser(t, pgDB) + + // add a workspace to use + w := model.Workspace{Name: uuid.NewString(), UserID: user.ID} + _, err := db.Bun().NewInsert().Model(&w).Exec(ctx) + require.NoError(t, err) + defer func() { + err := db.CleanupMockWorkspace([]int32{int32(w.ID)}) + if err != nil { + log.Errorf("error when cleaning up mock workspaces") + } + }() + + // add priority limit for global NTSC + globalLimit := 5 + wkspInput := model.NTSCTaskConfigPolicies{ + WorkloadType: model.NTSCType, + WorkspaceID: nil, + Constraints: model.Constraints{ + PriorityLimit: &globalLimit, + }, + LastUpdatedBy: user.ID, + } + err = SetNTSCConfigPolicies(ctx, &wkspInput) + require.NoError(t, err) + + // get priority limit + res, found, err := GetPriorityLimit(ctx, nil, model.NTSCType) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, globalLimit, res) + + // read experiment + res, found, err = GetPriorityLimit(ctx, nil, model.ExperimentType) + require.NoError(t, err) + require.False(t, found) + + // read invalid workload type + res, found, err = GetPriorityLimit(ctx, nil, "bogus") + require.Error(t, err) + require.False(t, found) +} + // Test the enforcement of the primary key on the task_config_polciies table. func TestTaskConfigPoliciesUnique(t *testing.T) { ctx := context.Background() diff --git a/master/internal/configpolicy/utils.go b/master/internal/configpolicy/utils.go index 9b240487a52..e5315658e3a 100644 --- a/master/internal/configpolicy/utils.go +++ b/master/internal/configpolicy/utils.go @@ -9,7 +9,6 @@ import ( "github.com/ghodss/yaml" "google.golang.org/protobuf/types/known/structpb" - "github.com/determined-ai/determined/master/internal/rm" "github.com/determined-ai/determined/master/pkg/model" "github.com/determined-ai/determined/master/pkg/protoutils" ) @@ -40,15 +39,10 @@ func GetPriorityLimitPrecedence(ctx context.Context, workspace_id int, workload_ return 0, false, nil } -// PriorityLimit returns the ne -func PriorityOK(currPriority int, priorityLimit int, resourceManager rm.ResourceManager) bool { - smallerHigher, err := resourceManager.SmallerValueIsHigherPriority() - if err != nil { - // RM does not have the concept of priority. No Limit applied. - return true - } +// PriorityOK returns true if the current priority is acceptable given the priority limit and resource manager. +func PriorityOK(currPriority int, priorityLimit int, smallerValueIsHigherPriority bool) bool { - if smallerHigher { + if smallerValueIsHigherPriority { return currPriority >= priorityLimit } diff --git a/master/internal/configpolicy/utils_intg_test.go b/master/internal/configpolicy/utils_intg_test.go new file mode 100644 index 00000000000..2bf1eeec315 --- /dev/null +++ b/master/internal/configpolicy/utils_intg_test.go @@ -0,0 +1,92 @@ +package configpolicy + +import ( + "context" + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + + "github.com/determined-ai/determined/master/internal/db" + "github.com/determined-ai/determined/master/pkg/etc" + "github.com/determined-ai/determined/master/pkg/model" +) + +func TestGetPriorityLimitPrecedence(t *testing.T) { + ctx := context.Background() + + require.NoError(t, etc.SetRootPath(db.RootFromDB)) + pgDB, cleanup := db.MustResolveNewPostgresDatabase(t) + defer cleanup() + db.MustMigrateTestPostgres(t, pgDB, db.MigrationsFromDB) + + // when no constraints are present, do not find constraints + _, found, err := GetPriorityLimitPrecedence(ctx, 10, model.NTSCType) + require.NoError(t, err) + require.False(t, found) + + // set priority limit for a workspace + wkspLimit := 50 + w := addWorkspacePriorityLimit(t, pgDB, wkspLimit) + + // workspace but none for global - get workspace limit + limit, found, err := GetPriorityLimitPrecedence(ctx, w.ID, model.NTSCType) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, wkspLimit, limit) + + // set global priority limit + globalLimit := 42 + addGlobalPriorityLimit(t, pgDB, globalLimit) + + // global and workspace - get global limit + limit, found, err = GetPriorityLimitPrecedence(ctx, w.ID, model.NTSCType) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, globalLimit, limit) + + // global but none for workspace - get global limit + limit, found, err = GetPriorityLimitPrecedence(ctx, w.ID+1, model.NTSCType) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, globalLimit, limit) +} + +func addWorkspacePriorityLimit(t *testing.T, pgDB *db.PgDB, limit int) model.Workspace { + ctx := context.Background() + user := db.RequireMockUser(t, pgDB) + + // add a workspace to use + w := model.Workspace{Name: uuid.NewString(), UserID: user.ID} + _, err := db.Bun().NewInsert().Model(&w).Exec(ctx) + require.NoError(t, err) + + input := model.NTSCTaskConfigPolicies{ + WorkloadType: model.NTSCType, + WorkspaceID: &w.ID, + Constraints: model.Constraints{ + PriorityLimit: &limit, + }, + LastUpdatedBy: user.ID, + } + err = SetNTSCConfigPolicies(ctx, &input) + require.NoError(t, err) + + return w +} + +func addGlobalPriorityLimit(t *testing.T, pgDB *db.PgDB, limit int) { + ctx := context.Background() + user := db.RequireMockUser(t, pgDB) + + input := model.NTSCTaskConfigPolicies{ + WorkloadType: model.NTSCType, + WorkspaceID: nil, + Constraints: model.Constraints{ + PriorityLimit: &limit, + }, + LastUpdatedBy: user.ID, + } + err := SetNTSCConfigPolicies(ctx, &input) + require.NoError(t, err) +} diff --git a/master/internal/configpolicy/utils_test.go b/master/internal/configpolicy/utils_test.go index a7ecfe8c7db..90a21d92cc0 100644 --- a/master/internal/configpolicy/utils_test.go +++ b/master/internal/configpolicy/utils_test.go @@ -30,6 +30,32 @@ func TestValidWorkloadType(t *testing.T) { } } +func TestPriorityOK(t *testing.T) { + + testCases := []struct { + name string + userPriority int + adminLimit int + smallerIsHigher bool + ok bool + }{ + {"smaller is higher - ok", 10, 1, true, true}, + {"smaller is higher - not ok", 10, 20, true, false}, + {"smaller is higher - equal", 20, 20, true, true}, + {"smaller is lower - ok", 11, 13, false, true}, + {"smaller is lower - not ok", 13, 11, false, false}, + {"smaller is lower - equal", 11, 11, false, true}, + } + + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + ok := PriorityOK(tt.userPriority, tt.adminLimit, tt.smallerIsHigher) + require.Equal(t, tt.ok, ok) + }) + } + +} + const yamlConstraints = ` constraints: resources: diff --git a/master/internal/job/jobservice/jobservice.go b/master/internal/job/jobservice/jobservice.go index 7666811fcb9..e0f7864a214 100644 --- a/master/internal/job/jobservice/jobservice.go +++ b/master/internal/job/jobservice/jobservice.go @@ -189,11 +189,7 @@ func (s *Service) applyUpdate(update *jobv1.QueueControl) error { switch action := update.GetAction().(type) { case *jobv1.QueueControl_Priority: - // TODO handle priority updates with new constraints priority := int(action.Priority) - // FIXME add rm as an argument? InternalExperimnt seems to have rm in it. What about workspace? - // TaskSpec seems to have workspace saved as a string - //wkspID := return j.SetJobPriority(priority) case *jobv1.QueueControl_Weight: if action.Weight <= 0 { diff --git a/master/internal/rm/agentrm/agent_resource_manager.go b/master/internal/rm/agentrm/agent_resource_manager.go index 7f31db3b686..013a327d0ea 100644 --- a/master/internal/rm/agentrm/agent_resource_manager.go +++ b/master/internal/rm/agentrm/agent_resource_manager.go @@ -108,11 +108,6 @@ func newAgentResourceManager( return a, nil } -// Type implements rm.ResourceManager. -func (a *ResourceManager) Type() string { - return rm.AgentRM -} - // SmallerValueIsHigherPriority returns true if smaller priority values indicate a higher priority level. func (a *ResourceManager) SmallerValueIsHigherPriority() (bool, error) { return true, nil diff --git a/master/internal/rm/dispatcherrm/dispatcher_resource_manager.go b/master/internal/rm/dispatcherrm/dispatcher_resource_manager.go index a9d8bd1cf30..d2e61d2c897 100644 --- a/master/internal/rm/dispatcherrm/dispatcher_resource_manager.go +++ b/master/internal/rm/dispatcherrm/dispatcher_resource_manager.go @@ -206,11 +206,6 @@ func New( return m, nil } -// Type implements rm.ResourceManager. -func (m *DispatcherResourceManager) Type() string { - return rm.SlurmType -} - // SmallerValueIsHigherPriority returns true if smaller priority values indicate a higher priority level. func (m *DispatcherResourceManager) SmallerValueIsHigherPriority() (bool, error) { return false, fmt.Errorf("priority not implemented") diff --git a/master/internal/rm/kubernetesrm/kubernetes_resource_manager.go b/master/internal/rm/kubernetesrm/kubernetes_resource_manager.go index 1e682306bc5..70ab0964c83 100644 --- a/master/internal/rm/kubernetesrm/kubernetes_resource_manager.go +++ b/master/internal/rm/kubernetesrm/kubernetes_resource_manager.go @@ -142,11 +142,6 @@ func New( return k, nil } -// Type implements rm.ResourceManager. -func (k *ResourceManager) Type() string { - return rm.KubernetesType -} - // SmallerValueIsHigherPriority returns true if smaller priority values indicate a higher priority level. func (k *ResourceManager) SmallerValueIsHigherPriority() (bool, error) { return false, nil diff --git a/master/internal/rm/multirm/multirm.go b/master/internal/rm/multirm/multirm.go index be782a09887..b096898682a 100644 --- a/master/internal/rm/multirm/multirm.go +++ b/master/internal/rm/multirm/multirm.go @@ -547,3 +547,8 @@ func (m *MultiRMRouter) fanOutRMCommand(f func(rm.ResourceManager) error) error } return nil } + +// SmallerValueIsHigherPriority returns true if smaller priority values indicate a higher priority level. +func (m *MultiRMRouter) SmallerValueIsHigherPriority() (bool, error) { + return false, nil +} diff --git a/master/internal/rm/resource_manager_iface.go b/master/internal/rm/resource_manager_iface.go index b7f972da24d..80b72302178 100644 --- a/master/internal/rm/resource_manager_iface.go +++ b/master/internal/rm/resource_manager_iface.go @@ -10,18 +10,6 @@ import ( "github.com/determined-ai/determined/proto/pkg/jobv1" ) -// Resource Manager types. -const ( - // Agent Resource Manager constant. - AgentRM string = "AGENT" - // Kubernetes Resource Manager constant. - KubernetesType string = "KUBERNETES" - // Multi RM constant. - MultiType string = "MultiRM" - // Slurm Resource Manager constant. - SlurmType string = "SLURM" -) - // ResourceManager is an interface for a resource manager, which can allocate and manage resources. type ResourceManager interface { // Basic functionality @@ -32,7 +20,6 @@ type ResourceManager interface { DeleteJob(sproto.DeleteJob) (sproto.DeleteJobResponse, error) NotifyContainerRunning(sproto.NotifyContainerRunning) error SmallerValueIsHigherPriority() (bool, error) - Type() string // Scheduling related stuff SetGroupMaxSlots(sproto.SetGroupMaxSlots)