diff --git a/.dockerignore b/.dockerignore index de9c2533..96a55e46 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,8 +4,10 @@ .claude *.log tmp/ -bin/ +bin/* +!bin/linux_amd64 !bin/linux_amd64/ax-task-runner +!bin/linux_arm64 !bin/linux_arm64/ax-task-runner ax ax-server diff --git a/DESIGN.md b/DESIGN.md index 6e880f80..849a0a83 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -53,7 +53,7 @@ The control plane exposes the `ax.v1alpha1.AX` gRPC service. Health checks are p |---|---| | `GetTask` | Get a task by atespace and name. | | `ListTasks` | List tasks in an atespace, with pagination. | -| `UpdateTask` | Create or update a task. | +| `CreateTask` | Create a task (tasks are immutable once created). | | `DeleteTask` | Delete a task. | | `SuspendTask` | Checkpoint actor state and pause the task. | | `ResumeTask` | Resume a suspended task. | diff --git a/cmd/ax/apply_test.go b/cmd/ax/apply_test.go new file mode 100644 index 00000000..3641a2a6 --- /dev/null +++ b/cmd/ax/apply_test.go @@ -0,0 +1,124 @@ +// Copyright 2026 Google LLC +// +// 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. + +package main + +import ( + "context" + "strings" + "testing" + + "github.com/google/ax/pkg/apis/v1alpha1" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "gopkg.in/yaml.v3" +) + +type mockAXClient struct { + v1alpha1.AXClient + createTaskFn func(ctx context.Context, in *v1alpha1.CreateTaskRequest, opts ...grpc.CallOption) (*v1alpha1.Task, error) + getWorkspaceFn func(ctx context.Context, in *v1alpha1.GetWorkspaceRequest, opts ...grpc.CallOption) (*v1alpha1.Workspace, error) + updateWorkspaceFn func(ctx context.Context, in *v1alpha1.UpdateWorkspaceRequest, opts ...grpc.CallOption) (*v1alpha1.Workspace, error) +} + +func (m *mockAXClient) CreateTask(ctx context.Context, in *v1alpha1.CreateTaskRequest, opts ...grpc.CallOption) (*v1alpha1.Task, error) { + if m.createTaskFn != nil { + return m.createTaskFn(ctx, in, opts...) + } + return m.AXClient.CreateTask(ctx, in, opts...) +} + +func (m *mockAXClient) GetWorkspace(ctx context.Context, in *v1alpha1.GetWorkspaceRequest, opts ...grpc.CallOption) (*v1alpha1.Workspace, error) { + if m.getWorkspaceFn != nil { + return m.getWorkspaceFn(ctx, in, opts...) + } + return m.AXClient.GetWorkspace(ctx, in, opts...) +} + +func (m *mockAXClient) UpdateWorkspace(ctx context.Context, in *v1alpha1.UpdateWorkspaceRequest, opts ...grpc.CallOption) (*v1alpha1.Workspace, error) { + if m.updateWorkspaceFn != nil { + return m.updateWorkspaceFn(ctx, in, opts...) + } + return m.AXClient.UpdateWorkspace(ctx, in, opts...) +} + +func TestApplyDocument_CreateNewTask(t *testing.T) { + manifestYAML := ` +apiVersion: ax.io/v1alpha1 +kind: Task +metadata: + name: my-task + atespace: default +spec: + image: ubuntu:latest + command: ["echo", "hello"] +` + var node yaml.Node + if err := yaml.Unmarshal([]byte(manifestYAML), &node); err != nil { + t.Fatalf("failed to parse YAML: %v", err) + } + + created := false + client := &mockAXClient{ + createTaskFn: func(ctx context.Context, in *v1alpha1.CreateTaskRequest, opts ...grpc.CallOption) (*v1alpha1.Task, error) { + created = true + return in.Task, nil + }, + } + + docNode := node.Content[0] + kind, name, outcome, err := applyDocument(context.Background(), client, docNode) + if err != nil { + t.Fatalf("expected applyDocument to succeed, got: %v", err) + } + if !created { + t.Errorf("expected CreateTask to be called") + } + if kind != "Task" || name != "my-task" || outcome != "created" { + t.Errorf("expected Task/my-task created, got %s/%s %s", kind, name, outcome) + } +} + +func TestApplyDocument_ExistingTaskFailsImmutable(t *testing.T) { + manifestYAML := ` +apiVersion: ax.io/v1alpha1 +kind: Task +metadata: + name: existing-task + atespace: default +spec: + image: ubuntu:latest + command: ["echo", "hello"] +` + var node yaml.Node + if err := yaml.Unmarshal([]byte(manifestYAML), &node); err != nil { + t.Fatalf("failed to parse YAML: %v", err) + } + + client := &mockAXClient{ + createTaskFn: func(ctx context.Context, in *v1alpha1.CreateTaskRequest, opts ...grpc.CallOption) (*v1alpha1.Task, error) { + return nil, status.Errorf(codes.FailedPrecondition, "task %s/%s already exists and is immutable", in.Task.GetMetadata().GetAtespace(), in.Task.GetMetadata().GetName()) + }, + } + + docNode := node.Content[0] + _, _, _, err := applyDocument(context.Background(), client, docNode) + if err == nil { + t.Fatalf("expected error applying to existing task, got nil") + } + if !strings.Contains(err.Error(), "already exists and is immutable") { + t.Errorf("expected error to mention 'already exists and is immutable', got %v", err) + } +} diff --git a/cmd/ax/main.go b/cmd/ax/main.go index 9771f464..0875177c 100644 --- a/cmd/ax/main.go +++ b/cmd/ax/main.go @@ -269,13 +269,11 @@ func applyDocument(ctx context.Context, client v1alpha1.AXClient, doc *yaml.Node if err := doc.Decode(&task); err != nil { return "", "", "", err } - existing, err := client.GetTask(ctx, &v1alpha1.GetTaskRequest{Atespace: task.GetMetadata().GetAtespace(), Name: task.GetMetadata().GetName()}) - outcome, err := applyOutcome(err, existing.GetSpec(), task.GetSpec()) + res, err := client.CreateTask(ctx, &v1alpha1.CreateTaskRequest{Task: &task}) if err != nil { return "", "", "", err } - res, err := client.UpdateTask(ctx, &v1alpha1.UpdateTaskRequest{Task: &task}) - return head.Kind, res.GetMetadata().GetName(), outcome, err + return head.Kind, res.GetMetadata().GetName(), "created", nil case v1alpha1.KindWorkspace: var ws v1alpha1.Workspace diff --git a/demo.sh b/demo.sh index a0cf6e2f..5ab756a8 100755 --- a/demo.sh +++ b/demo.sh @@ -36,7 +36,7 @@ ax() { "${AX_BIN}" "$@"; } ATESPACE="${ATESPACE:-default}" TASK_NAME="demo-task" WORKSPACE_NAME="demo-workspace" -TASK_IMAGE="${AX_TASK_IMAGE:-${AX_IMAGE_REPO:-gcr.io/dberkov-gke-dev3}/ax-task-runner@sha256:127dbe6650f2b93e5af793a9d7995ce0cf70c0f37ffb4c696154d3cc1a32f8bd}" +TASK_IMAGE="${AX_TASK_IMAGE:-${AX_IMAGE_REPO:-gcr.io/ax-substrate/ate-images}/ax-task-runner@sha256:464c5a53c68c67e929dbbb5450f1eb41f99b2742efcf42b721c09825a58397f1}" # --------------------------------------------------------------------------- # Presentation helpers @@ -169,8 +169,9 @@ YAML printf '%s' "${DIM}"; sed 's/^/ /' "${DEMO_YAML}"; printf '%s\n\n' "${RESET}" run ax apply -f "${DEMO_YAML}" -step "Watch the task come up" -note "The controller creates an actor on Agent Substrate and initializes /workspace." +step "Resume the task and watch it come up" +note "New tasks are created Suspended by default. Resuming creates the worker on Agent Substrate and initializes /workspace." +run ax resume task "${TASK_NAME}" -a "${ATESPACE}" wait_for "Running" "True" ok "${TASK_NAME} is Running and Ready" echo diff --git a/deploy/ax-controller.yaml b/deploy/ax-controller.yaml index 1e6054bf..66c2c44b 100644 --- a/deploy/ax-controller.yaml +++ b/deploy/ax-controller.yaml @@ -80,7 +80,7 @@ spec: - name: ATENET_ROUTER_ADDR value: "atenet-router.ate-system.svc.cluster.local:80" - name: AX_SNAPSHOTS_BUCKET - value: "gs://dberkov-gke-dev3/ate-env/" + value: "gs://snapshot-substrate-test-ax-substrate/ate-env/" resources: requests: cpu: "100m" diff --git a/docs/runner.md b/docs/runner.md index d9bfff45..30bc1653 100644 --- a/docs/runner.md +++ b/docs/runner.md @@ -14,7 +14,7 @@ The controller does not run `spec.command` as the container entrypoint. It alway |---|---| | Container image | `spec.image`, or the default `ax-task-runner` image when unset | | Container command | `/usr/local/bin/ax-task-runner`, always | -| `AX_TASK_YAML` | The `Task` launch configuration as YAML, excluding status and the suspend flag | +| `AX_TASK_YAML` | The `Task` launch configuration as YAML, excluding status | | `AX_WORKSPACES_YAML` | Every bound `Workspace` resource as a multi-document YAML stream, in the task's binding order | | `spec.env` entries | Each one set directly in the container environment | | `GEMINI_API_KEY` | Set when the atespace has a Gemini credential configured | diff --git a/docs/sandbox.md b/docs/sandbox.md index f582278c..adc4797e 100644 --- a/docs/sandbox.md +++ b/docs/sandbox.md @@ -17,7 +17,7 @@ The daemon speaks HTTP/1.1 and `h2c` on the same port. Your agent can introspect |---|---|---|---| | `/healthz` | `GET` | `text/plain` | Liveness. Always `200 OK`. | | `/readyz` | `GET` | `text/plain` | Readiness. `503` while the workspace is initializing, `200` once clones, MCP config, and skills are in place. | -| `/metadata/v1alpha1/ax/task` | `GET` | `application/yaml` | Task launch configuration, excluding status and the suspend flag. | +| `/metadata/v1alpha1/ax/task` | `GET` | `application/yaml` | Task launch configuration, excluding status. | | `/metadata/v1alpha1/ax/workspaces` | `GET` | `application/yaml` | Every bound `Workspace`, as a multi-document stream in binding order. | ```bash diff --git a/internal/controller/reconciler.go b/internal/controller/reconciler.go index 8a3cde17..2b4a56ea 100644 --- a/internal/controller/reconciler.go +++ b/internal/controller/reconciler.go @@ -154,11 +154,10 @@ func (r *TaskReconciler) Reconcile(ctx context.Context, task *v1alpha1.Task, wor extraEnv[geminiSecretKey] = geminiKey } - // Only launch configuration belongs in the template; status and suspend - // changes must not create new golden snapshots. + // Only launch configuration belongs in the template; status changes + // must not create new golden snapshots. launchTask := proto.Clone(task).(*v1alpha1.Task) launchTask.Status = nil - launchTask.Spec.Suspend = false if taskYAML, err := yaml.Marshal(launchTask); err == nil { extraEnv["AX_TASK_YAML"] = string(taskYAML) } @@ -191,12 +190,11 @@ func (r *TaskReconciler) Reconcile(ctx context.Context, task *v1alpha1.Task, wor } // 4. Suspend or Resume the Actor - if task.Spec != nil && task.Spec.Suspend { + // Tasks are suspended by default upon creation until explicitly resumed to "Running". + if task.Status.Phase == "Suspended" || task.Status.Phase == "" { slog.Info("suspending actor on Substrate", "actor", actorName) if err := r.client.SuspendActor(ctx, atespace, actorName); err != nil { - r.setNotReady(task, "ActorSuspendFailed", err.Error(), now) - task.Status.Phase = "Failed" - return task, fmt.Errorf("suspending actor: %w", err) + slog.Warn("could not suspend actor on Substrate", "error", err) } task.Status.WorkerIp = "" task.Status.Phase = "Suspended" diff --git a/internal/controller/reconciler_test.go b/internal/controller/reconciler_test.go index 94396024..71431095 100644 --- a/internal/controller/reconciler_test.go +++ b/internal/controller/reconciler_test.go @@ -187,7 +187,7 @@ func TestTaskReconciler(t *testing.T) { }, // A client-supplied actor name must not survive: the actor is always // named after the task. - Status: &v1alpha1.TaskStatus{Actor: "not-the-task"}, + Status: &v1alpha1.TaskStatus{Actor: "not-the-task", Phase: "Running"}, } reconciled, err := reconciler.Reconcile(ctx, task) @@ -251,8 +251,7 @@ func TestTaskReconciler_Suspend(t *testing.T) { Atespace: "default", }, Spec: &v1alpha1.TaskSpec{ - Suspend: true, - Image: "ghrc.io/my-org/my-image", + Image: "ghrc.io/my-org/my-image", }, } @@ -329,6 +328,9 @@ func TestTaskReconciler_WorkspaceReady(t *testing.T) { Atespace: "default", }, Spec: &v1alpha1.TaskSpec{}, + Status: &v1alpha1.TaskStatus{ + Phase: "Running", + }, } // Case 1: Worker not responding on readyz -> WorkspaceReady=False and Ready=False. @@ -351,7 +353,7 @@ func TestTaskReconciler_WorkspaceReady(t *testing.T) { // Case 3: Suspending the task -> Ready=False (TaskSuspended), but the workspace was // already initialized so WorkspaceReady stays True. task = reconciledReady - task.Spec.Suspend = true + task.Status.Phase = "Suspended" reconciledSuspended, err := reconciler.Reconcile(ctx, task, nil) if err != nil { t.Fatalf("Reconcile with suspend failed: %v", err) @@ -366,7 +368,7 @@ func TestTaskReconciler_WorkspaceReady(t *testing.T) { // WorkspaceReady instead of re-polling, so the task is Ready again immediately. mockSrv.workerIP = "127.0.0.1:1" task = reconciledSuspended - task.Spec.Suspend = false + task.Status.Phase = "Running" reconciledResumed, err := reconciler.Reconcile(ctx, task, nil) if err != nil { t.Fatalf("Reconcile with resume failed: %v", err) diff --git a/internal/server/server.go b/internal/server/server.go index 82fbabd6..c9350509 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -45,7 +45,7 @@ func NewServer(s store.Store) *Server { return srv } -// GRPCServer returns the underlying gRPC server. +// GRPCServer returns the underlying gRPC server instance. func (s *Server) GRPCServer() *grpc.Server { return s.grpcServer } @@ -108,7 +108,7 @@ func (s *Server) ListTasks(ctx context.Context, req *v1alpha1.ListTasksRequest) return &v1alpha1.ListTasksResponse{Tasks: tasks}, nil } -func (s *Server) UpdateTask(ctx context.Context, req *v1alpha1.UpdateTaskRequest) (*v1alpha1.Task, error) { +func (s *Server) CreateTask(ctx context.Context, req *v1alpha1.CreateTaskRequest) (*v1alpha1.Task, error) { if req == nil || req.Task == nil { return nil, status.Error(codes.InvalidArgument, "task required") } @@ -116,13 +116,29 @@ func (s *Server) UpdateTask(ctx context.Context, req *v1alpha1.UpdateTaskRequest if err := v1alpha1.ValidateTask(task); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } - task.Metadata = defaultMetadata(task.Metadata, func(atespace, name string) *v1alpha1.ObjectMeta { - existing, err := s.store.GetTask(ctx, atespace, name) - if err != nil { - return nil - } - return existing.GetMetadata() - }) + if task.Metadata == nil { + task.Metadata = &v1alpha1.ObjectMeta{} + } + atespace := task.Metadata.Atespace + if atespace == "" { + atespace = "default" + task.Metadata.Atespace = atespace + } + _, err := s.store.GetTask(ctx, atespace, task.Metadata.GetName()) + if err == nil { + return nil, status.Errorf(codes.FailedPrecondition, "task %s/%s already exists and is immutable", atespace, task.Metadata.GetName()) + } + if !errors.Is(err, store.ErrNotFound) { + return nil, status.Errorf(codes.Internal, "checking existing task: %v", err) + } + + if task.Metadata.CreationTimestamp == nil { + task.Metadata.CreationTimestamp = timestamppb.Now() + } + if task.Status == nil { + task.Status = &v1alpha1.TaskStatus{} + } + task.Status.Phase = "Suspended" if err := s.store.SaveTask(ctx, task); err != nil { return nil, status.Errorf(codes.Internal, "saving task: %v", err) } @@ -163,10 +179,10 @@ func (s *Server) SuspendTask(ctx context.Context, req *v1alpha1.SuspendTaskReque } return nil, status.Errorf(codes.Internal, "getting task: %v", err) } - if task.Spec == nil { - task.Spec = &v1alpha1.TaskSpec{} + if task.Status == nil { + task.Status = &v1alpha1.TaskStatus{} } - task.Spec.Suspend = true + task.Status.Phase = "Suspended" if err := s.store.SaveTask(ctx, task); err != nil { return nil, status.Errorf(codes.Internal, "suspending task: %v", err) } @@ -188,10 +204,10 @@ func (s *Server) ResumeTask(ctx context.Context, req *v1alpha1.ResumeTaskRequest } return nil, status.Errorf(codes.Internal, "getting task: %v", err) } - if task.Spec == nil { - task.Spec = &v1alpha1.TaskSpec{} + if task.Status == nil { + task.Status = &v1alpha1.TaskStatus{} } - task.Spec.Suspend = false + task.Status.Phase = "Running" if err := s.store.SaveTask(ctx, task); err != nil { return nil, status.Errorf(codes.Internal, "resuming task: %v", err) } @@ -367,7 +383,11 @@ func defaultMetadata(meta *v1alpha1.ObjectMeta, existing func(atespace, name str meta.Atespace = "default" } if meta.CreationTimestamp == nil { - if prev := existing(meta.Atespace, meta.Name); prev.GetCreationTimestamp() != nil { + var prev *v1alpha1.ObjectMeta + if existing != nil { + prev = existing(meta.Atespace, meta.Name) + } + if prev.GetCreationTimestamp() != nil { meta.CreationTimestamp = prev.GetCreationTimestamp() } else { meta.CreationTimestamp = timestamppb.Now() diff --git a/internal/server/server_test.go b/internal/server/server_test.go index ef144c9f..c38af675 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -101,11 +101,11 @@ func TestServerGRPC(t *testing.T) { }}); err != nil { t.Fatalf("UpdateModel failed: %v", err) } - if _, err := client.UpdateTask(ctx, &v1alpha1.UpdateTaskRequest{Task: &v1alpha1.Task{ + if _, err := client.CreateTask(ctx, &v1alpha1.CreateTaskRequest{Task: &v1alpha1.Task{ Metadata: &v1alpha1.ObjectMeta{Name: "grpc-task"}, Spec: &v1alpha1.TaskSpec{Image: "alpine"}, }}); err != nil { - t.Fatalf("UpdateTask failed: %v", err) + t.Fatalf("CreateTask failed: %v", err) } // 2. Defaulting applies to every kind: atespace and creation timestamp are filled in. @@ -140,14 +140,14 @@ func TestServerGRPC(t *testing.T) { t.Errorf("expected creation timestamp on listed task") } - // Test UpdateTask + // Test that Task is immutable task.Spec.Image = "ghcr.io/test/updated-image" - updatedTask, err := client.UpdateTask(ctx, &v1alpha1.UpdateTaskRequest{Task: task}) - if err != nil { - t.Fatalf("UpdateTask failed: %v", err) + _, err = client.CreateTask(ctx, &v1alpha1.CreateTaskRequest{Task: task}) + if err == nil { + t.Fatalf("expected CreateTask to fail on existing task because tasks are immutable") } - if updatedTask.Spec.Image != "ghcr.io/test/updated-image" { - t.Errorf("expected image 'ghcr.io/test/updated-image', got %s", updatedTask.Spec.Image) + if status.Code(err) != codes.FailedPrecondition { + t.Errorf("expected FailedPrecondition code, got %v", status.Code(err)) } // 4. Suspend & Resume Task @@ -155,16 +155,16 @@ func TestServerGRPC(t *testing.T) { if err != nil { t.Fatalf("SuspendTask failed: %v", err) } - if !suspTask.Spec.Suspend { - t.Errorf("expected task to be suspended") + if suspTask.Status.Phase != "Suspended" { + t.Errorf("expected task phase to be 'Suspended', got %q", suspTask.Status.Phase) } resTask, err := client.ResumeTask(ctx, &v1alpha1.ResumeTaskRequest{Atespace: "default", Name: "grpc-task"}) if err != nil { t.Fatalf("ResumeTask failed: %v", err) } - if resTask.Spec.Suspend { - t.Errorf("expected task to be resumed") + if resTask.Status.Phase != "Running" { + t.Errorf("expected task phase to be 'Running', got %q", resTask.Status.Phase) } @@ -255,7 +255,7 @@ func TestServerGRPC(t *testing.T) { // Names and atespaces become Substrate resource names, which must be RFC 1123 // labels. The server rejects them up front instead of letting the controller // fail asynchronously with ActorCreationFailed. -func TestUpdate_RejectsInvalidNames(t *testing.T) { +func TestCreate_RejectsInvalidNames(t *testing.T) { srv := server.NewServer(memory.NewStore()) ctx := context.Background() @@ -265,8 +265,8 @@ func TestUpdate_RejectsInvalidNames(t *testing.T) { {Name: ""}, {Name: "ok", Atespace: "Not-Lowercase"}, } { - if _, err := srv.UpdateTask(ctx, &v1alpha1.UpdateTaskRequest{Task: &v1alpha1.Task{Metadata: meta}}); status.Code(err) != codes.InvalidArgument { - t.Errorf("UpdateTask(%v): got %v, want InvalidArgument", meta, err) + if _, err := srv.CreateTask(ctx, &v1alpha1.CreateTaskRequest{Task: &v1alpha1.Task{Metadata: meta}}); status.Code(err) != codes.InvalidArgument { + t.Errorf("CreateTask(%v): got %v, want InvalidArgument", meta, err) } if _, err := srv.UpdateWorkspace(ctx, &v1alpha1.UpdateWorkspaceRequest{Workspace: &v1alpha1.Workspace{Metadata: meta}}); status.Code(err) != codes.InvalidArgument { t.Errorf("UpdateWorkspace(%v): got %v, want InvalidArgument", meta, err) @@ -283,8 +283,8 @@ func TestUpdate_RejectsInvalidNames(t *testing.T) { // Valid names still go through, with and without an explicit atespace. good := &v1alpha1.ObjectMeta{Name: "task-with-caps", Atespace: "team-a"} - if _, err := srv.UpdateTask(ctx, &v1alpha1.UpdateTaskRequest{Task: &v1alpha1.Task{Metadata: good}}); err != nil { - t.Errorf("UpdateTask(%v): %v", good, err) + if _, err := srv.CreateTask(ctx, &v1alpha1.CreateTaskRequest{Task: &v1alpha1.Task{Metadata: good}}); err != nil { + t.Errorf("CreateTask(%v): %v", good, err) } if _, err := srv.UpdateWorkspace(ctx, &v1alpha1.UpdateWorkspaceRequest{Workspace: &v1alpha1.Workspace{Metadata: &v1alpha1.ObjectMeta{Name: "ws-1"}}}); err != nil { t.Errorf("UpdateWorkspace: %v", err) @@ -294,11 +294,11 @@ func TestUpdate_RejectsInvalidNames(t *testing.T) { } } -func TestUpdateTask_ValidatesWorkspaceBindings(t *testing.T) { +func TestCreateTask_ValidatesWorkspaceBindings(t *testing.T) { srv := server.NewServer(memory.NewStore()) ctx := context.Background() - _, err := srv.UpdateTask(ctx, &v1alpha1.UpdateTaskRequest{Task: &v1alpha1.Task{ + _, err := srv.CreateTask(ctx, &v1alpha1.CreateTaskRequest{Task: &v1alpha1.Task{ Metadata: &v1alpha1.ObjectMeta{Name: "bad"}, Spec: &v1alpha1.TaskSpec{ Workspaces: []*v1alpha1.WorkspaceRef{{Name: "a", Path: "/same"}, {Name: "b", Path: "/same"}}, @@ -308,7 +308,7 @@ func TestUpdateTask_ValidatesWorkspaceBindings(t *testing.T) { t.Fatalf("expected InvalidArgument for colliding workspace paths, got %v", err) } - _, err = srv.UpdateTask(ctx, &v1alpha1.UpdateTaskRequest{Task: &v1alpha1.Task{ + _, err = srv.CreateTask(ctx, &v1alpha1.CreateTaskRequest{Task: &v1alpha1.Task{ Metadata: &v1alpha1.ObjectMeta{Name: "good"}, Spec: &v1alpha1.TaskSpec{ Workspaces: []*v1alpha1.WorkspaceRef{{Name: "a"}, {Name: "b"}}, diff --git a/internal/substrate/client.go b/internal/substrate/client.go index e3a32d29..b0273e87 100644 --- a/internal/substrate/client.go +++ b/internal/substrate/client.go @@ -205,7 +205,7 @@ func (c *Client) GetActorTemplate(ctx context.Context, atespace, templateName st const ( DefaultGuestCommand = "/usr/local/bin/ax-task-runner" - DefaultSnapshotsBucket = "gs://dberkov-gke-dev3/ate-env/" + DefaultSnapshotsBucket = "gs://snapshot-substrate-test-ax-substrate/ate-env/" ) // BuildActorTemplate constructs a Substrate ActorTemplate based on the standard ate-env specification. diff --git a/pkg/apis/v1alpha1/ax.pb.go b/pkg/apis/v1alpha1/ax.pb.go index 56f60109..fa3d02e4 100644 --- a/pkg/apis/v1alpha1/ax.pb.go +++ b/pkg/apis/v1alpha1/ax.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v5.28.2 +// protoc v7.34.1 // source: pkg/apis/v1alpha1/ax.proto package v1alpha1 @@ -176,17 +176,16 @@ func (x *Task) GetStatus() *TaskStatus { type TaskSpec struct { state protoimpl.MessageState `protogen:"open.v1"` - Suspend bool `protobuf:"varint,2,opt,name=suspend,proto3" json:"suspend,omitempty"` - Image string `protobuf:"bytes,3,opt,name=image,proto3" json:"image,omitempty"` - Command []string `protobuf:"bytes,4,rep,name=command,proto3" json:"command,omitempty"` - Env []*EnvVar `protobuf:"bytes,5,rep,name=env,proto3" json:"env,omitempty"` - Resources *ResourceReqs `protobuf:"bytes,6,opt,name=resources,proto3" json:"resources,omitempty"` + Image string `protobuf:"bytes,1,opt,name=image,proto3" json:"image,omitempty"` + Command []string `protobuf:"bytes,2,rep,name=command,proto3" json:"command,omitempty"` + Env []*EnvVar `protobuf:"bytes,3,rep,name=env,proto3" json:"env,omitempty"` + Resources *ResourceReqs `protobuf:"bytes,4,opt,name=resources,proto3" json:"resources,omitempty"` // workspaces binds one or more Workspaces, each mounted at its own path // under /workspace. The first entry is the task command's working directory. - Workspaces []*WorkspaceRef `protobuf:"bytes,7,rep,name=workspaces,proto3" json:"workspaces,omitempty"` + Workspaces []*WorkspaceRef `protobuf:"bytes,5,rep,name=workspaces,proto3" json:"workspaces,omitempty"` // debug enables the in-container guest services (process execution and file // access) that back `ax ssh`. Off by default. - Debug bool `protobuf:"varint,10,opt,name=debug,proto3" json:"debug,omitempty"` + Debug bool `protobuf:"varint,6,opt,name=debug,proto3" json:"debug,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -221,13 +220,6 @@ func (*TaskSpec) Descriptor() ([]byte, []int) { return file_pkg_apis_v1alpha1_ax_proto_rawDescGZIP(), []int{2} } -func (x *TaskSpec) GetSuspend() bool { - if x != nil { - return x.Suspend - } - return false -} - func (x *TaskSpec) GetImage() string { if x != nil { return x.Image @@ -1618,27 +1610,27 @@ func (x *ListTasksResponse) GetTasks() []*Task { return nil } -type UpdateTaskRequest struct { +type CreateTaskRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Task *Task `protobuf:"bytes,1,opt,name=task,proto3" json:"task,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *UpdateTaskRequest) Reset() { - *x = UpdateTaskRequest{} +func (x *CreateTaskRequest) Reset() { + *x = CreateTaskRequest{} mi := &file_pkg_apis_v1alpha1_ax_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *UpdateTaskRequest) String() string { +func (x *CreateTaskRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*UpdateTaskRequest) ProtoMessage() {} +func (*CreateTaskRequest) ProtoMessage() {} -func (x *UpdateTaskRequest) ProtoReflect() protoreflect.Message { +func (x *CreateTaskRequest) ProtoReflect() protoreflect.Message { mi := &file_pkg_apis_v1alpha1_ax_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1650,12 +1642,12 @@ func (x *UpdateTaskRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use UpdateTaskRequest.ProtoReflect.Descriptor instead. -func (*UpdateTaskRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use CreateTaskRequest.ProtoReflect.Descriptor instead. +func (*CreateTaskRequest) Descriptor() ([]byte, []int) { return file_pkg_apis_v1alpha1_ax_proto_rawDescGZIP(), []int{25} } -func (x *UpdateTaskRequest) GetTask() *Task { +func (x *CreateTaskRequest) GetTask() *Task { if x != nil { return x.Task } @@ -2520,19 +2512,16 @@ const file_pkg_apis_v1alpha1_ax_proto_rawDesc = "" + "\x04kind\x18\x02 \x01(\tR\x04kind\x123\n" + "\bmetadata\x18\x03 \x01(\v2\x17.ax.v1alpha1.ObjectMetaR\bmetadata\x12)\n" + "\x04spec\x18\x04 \x01(\v2\x15.ax.v1alpha1.TaskSpecR\x04spec\x12/\n" + - "\x06status\x18\x05 \x01(\v2\x17.ax.v1alpha1.TaskStatusR\x06status\"\xb0\x02\n" + - "\bTaskSpec\x12\x18\n" + - "\asuspend\x18\x02 \x01(\bR\asuspend\x12\x14\n" + - "\x05image\x18\x03 \x01(\tR\x05image\x12\x18\n" + - "\acommand\x18\x04 \x03(\tR\acommand\x12%\n" + - "\x03env\x18\x05 \x03(\v2\x13.ax.v1alpha1.EnvVarR\x03env\x127\n" + - "\tresources\x18\x06 \x01(\v2\x19.ax.v1alpha1.ResourceReqsR\tresources\x129\n" + + "\x06status\x18\x05 \x01(\v2\x17.ax.v1alpha1.TaskStatusR\x06status\"\xeb\x01\n" + + "\bTaskSpec\x12\x14\n" + + "\x05image\x18\x01 \x01(\tR\x05image\x12\x18\n" + + "\acommand\x18\x02 \x03(\tR\acommand\x12%\n" + + "\x03env\x18\x03 \x03(\v2\x13.ax.v1alpha1.EnvVarR\x03env\x127\n" + + "\tresources\x18\x04 \x01(\v2\x19.ax.v1alpha1.ResourceReqsR\tresources\x129\n" + "\n" + - "workspaces\x18\a \x03(\v2\x19.ax.v1alpha1.WorkspaceRefR\n" + + "workspaces\x18\x05 \x03(\v2\x19.ax.v1alpha1.WorkspaceRefR\n" + "workspaces\x12\x14\n" + - "\x05debug\x18\n" + - " \x01(\bR\x05debugJ\x04\b\x01\x10\x02J\x04\b\b\x10\tJ\x04\b\t\x10\n" + - "R\x04goalR\agatewayR\bpolicies\"2\n" + + "\x05debug\x18\x06 \x01(\bR\x05debug\"2\n" + "\x06EnvVar\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value\"x\n" + @@ -2638,7 +2627,7 @@ const file_pkg_apis_v1alpha1_ax_proto_rawDesc = "" + "\x06offset\x18\x03 \x01(\x03R\x06offset\"<\n" + "\x11ListTasksResponse\x12'\n" + "\x05tasks\x18\x01 \x03(\v2\x11.ax.v1alpha1.TaskR\x05tasks\":\n" + - "\x11UpdateTaskRequest\x12%\n" + + "\x11CreateTaskRequest\x12%\n" + "\x04task\x18\x01 \x01(\v2\x11.ax.v1alpha1.TaskR\x04task\"C\n" + "\x11DeleteTaskRequest\x12\x1a\n" + "\batespace\x18\x01 \x01(\tR\batespace\x12\x12\n" + @@ -2688,7 +2677,7 @@ const file_pkg_apis_v1alpha1_ax_proto_rawDesc = "" + "\aGetTask\x12\x1b.ax.v1alpha1.GetTaskRequest\x1a\x11.ax.v1alpha1.Task\x12J\n" + "\tListTasks\x12\x1d.ax.v1alpha1.ListTasksRequest\x1a\x1e.ax.v1alpha1.ListTasksResponse\x12?\n" + "\n" + - "UpdateTask\x12\x1e.ax.v1alpha1.UpdateTaskRequest\x1a\x11.ax.v1alpha1.Task\x12M\n" + + "CreateTask\x12\x1e.ax.v1alpha1.CreateTaskRequest\x1a\x11.ax.v1alpha1.Task\x12M\n" + "\n" + "DeleteTask\x12\x1e.ax.v1alpha1.DeleteTaskRequest\x1a\x1f.ax.v1alpha1.DeleteTaskResponse\x12A\n" + "\vSuspendTask\x12\x1f.ax.v1alpha1.SuspendTaskRequest\x1a\x11.ax.v1alpha1.Task\x12?\n" + @@ -2744,7 +2733,7 @@ var file_pkg_apis_v1alpha1_ax_proto_goTypes = []any{ (*GetTaskRequest)(nil), // 22: ax.v1alpha1.GetTaskRequest (*ListTasksRequest)(nil), // 23: ax.v1alpha1.ListTasksRequest (*ListTasksResponse)(nil), // 24: ax.v1alpha1.ListTasksResponse - (*UpdateTaskRequest)(nil), // 25: ax.v1alpha1.UpdateTaskRequest + (*CreateTaskRequest)(nil), // 25: ax.v1alpha1.CreateTaskRequest (*DeleteTaskRequest)(nil), // 26: ax.v1alpha1.DeleteTaskRequest (*DeleteTaskResponse)(nil), // 27: ax.v1alpha1.DeleteTaskResponse (*SuspendTaskRequest)(nil), // 28: ax.v1alpha1.SuspendTaskRequest @@ -2795,7 +2784,7 @@ var file_pkg_apis_v1alpha1_ax_proto_depIdxs = []int32{ 21, // 25: ax.v1alpha1.ModelSpec.secret_key:type_name -> ax.v1alpha1.SecretKeyRef 45, // 26: ax.v1alpha1.ModelSpec.parameters:type_name -> google.protobuf.Struct 1, // 27: ax.v1alpha1.ListTasksResponse.tasks:type_name -> ax.v1alpha1.Task - 1, // 28: ax.v1alpha1.UpdateTaskRequest.task:type_name -> ax.v1alpha1.Task + 1, // 28: ax.v1alpha1.CreateTaskRequest.task:type_name -> ax.v1alpha1.Task 1, // 29: ax.v1alpha1.WatchTaskResponse.task:type_name -> ax.v1alpha1.Task 11, // 30: ax.v1alpha1.ListWorkspacesResponse.workspaces:type_name -> ax.v1alpha1.Workspace 11, // 31: ax.v1alpha1.UpdateWorkspaceRequest.workspace:type_name -> ax.v1alpha1.Workspace @@ -2803,7 +2792,7 @@ var file_pkg_apis_v1alpha1_ax_proto_depIdxs = []int32{ 19, // 33: ax.v1alpha1.UpdateModelRequest.model:type_name -> ax.v1alpha1.Model 22, // 34: ax.v1alpha1.AX.GetTask:input_type -> ax.v1alpha1.GetTaskRequest 23, // 35: ax.v1alpha1.AX.ListTasks:input_type -> ax.v1alpha1.ListTasksRequest - 25, // 36: ax.v1alpha1.AX.UpdateTask:input_type -> ax.v1alpha1.UpdateTaskRequest + 25, // 36: ax.v1alpha1.AX.CreateTask:input_type -> ax.v1alpha1.CreateTaskRequest 26, // 37: ax.v1alpha1.AX.DeleteTask:input_type -> ax.v1alpha1.DeleteTaskRequest 28, // 38: ax.v1alpha1.AX.SuspendTask:input_type -> ax.v1alpha1.SuspendTaskRequest 29, // 39: ax.v1alpha1.AX.ResumeTask:input_type -> ax.v1alpha1.ResumeTaskRequest @@ -2818,7 +2807,7 @@ var file_pkg_apis_v1alpha1_ax_proto_depIdxs = []int32{ 42, // 48: ax.v1alpha1.AX.DeleteModel:input_type -> ax.v1alpha1.DeleteModelRequest 1, // 49: ax.v1alpha1.AX.GetTask:output_type -> ax.v1alpha1.Task 24, // 50: ax.v1alpha1.AX.ListTasks:output_type -> ax.v1alpha1.ListTasksResponse - 1, // 51: ax.v1alpha1.AX.UpdateTask:output_type -> ax.v1alpha1.Task + 1, // 51: ax.v1alpha1.AX.CreateTask:output_type -> ax.v1alpha1.Task 27, // 52: ax.v1alpha1.AX.DeleteTask:output_type -> ax.v1alpha1.DeleteTaskResponse 1, // 53: ax.v1alpha1.AX.SuspendTask:output_type -> ax.v1alpha1.Task 1, // 54: ax.v1alpha1.AX.ResumeTask:output_type -> ax.v1alpha1.Task diff --git a/pkg/apis/v1alpha1/ax.proto b/pkg/apis/v1alpha1/ax.proto index b67293a1..518f5a23 100644 --- a/pkg/apis/v1alpha1/ax.proto +++ b/pkg/apis/v1alpha1/ax.proto @@ -29,7 +29,7 @@ service AX { // Tasks rpc GetTask(GetTaskRequest) returns (Task); rpc ListTasks(ListTasksRequest) returns (ListTasksResponse); - rpc UpdateTask(UpdateTaskRequest) returns (Task); + rpc CreateTask(CreateTaskRequest) returns (Task); rpc DeleteTask(DeleteTaskRequest) returns (DeleteTaskResponse); rpc SuspendTask(SuspendTaskRequest) returns (Task); rpc ResumeTask(ResumeTaskRequest) returns (Task); @@ -68,26 +68,16 @@ message Task { } message TaskSpec { - // Field 1 was `goal`, removed; the workspace goal lives on WorkspaceRef. - reserved 1; - reserved "goal"; - bool suspend = 2; - string image = 3; - repeated string command = 4; - repeated EnvVar env = 5; - ResourceReqs resources = 6; + string image = 1; + repeated string command = 2; + repeated EnvVar env = 3; + ResourceReqs resources = 4; // workspaces binds one or more Workspaces, each mounted at its own path // under /workspace. The first entry is the task command's working directory. - repeated WorkspaceRef workspaces = 7; - // Field 8 was `gateway`, removed. - reserved 8; - reserved "gateway"; - // Field 9 was `policies` (budget and approval config), removed for now. - reserved 9; - reserved "policies"; + repeated WorkspaceRef workspaces = 5; // debug enables the in-container guest services (process execution and file // access) that back `ax ssh`. Off by default. - bool debug = 10; + bool debug = 6; } message EnvVar { @@ -239,7 +229,7 @@ message ListTasksResponse { repeated Task tasks = 1; } -message UpdateTaskRequest { +message CreateTaskRequest { Task task = 1; } diff --git a/pkg/apis/v1alpha1/ax_grpc.pb.go b/pkg/apis/v1alpha1/ax_grpc.pb.go index 1bf28d74..dcebb751 100644 --- a/pkg/apis/v1alpha1/ax_grpc.pb.go +++ b/pkg/apis/v1alpha1/ax_grpc.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v5.28.2 +// - protoc-gen-go-grpc v1.6.0 +// - protoc v7.34.1 // source: pkg/apis/v1alpha1/ax.proto package v1alpha1 @@ -35,7 +35,7 @@ const _ = grpc.SupportPackageIsVersion9 const ( AX_GetTask_FullMethodName = "/ax.v1alpha1.AX/GetTask" AX_ListTasks_FullMethodName = "/ax.v1alpha1.AX/ListTasks" - AX_UpdateTask_FullMethodName = "/ax.v1alpha1.AX/UpdateTask" + AX_CreateTask_FullMethodName = "/ax.v1alpha1.AX/CreateTask" AX_DeleteTask_FullMethodName = "/ax.v1alpha1.AX/DeleteTask" AX_SuspendTask_FullMethodName = "/ax.v1alpha1.AX/SuspendTask" AX_ResumeTask_FullMethodName = "/ax.v1alpha1.AX/ResumeTask" @@ -59,7 +59,7 @@ type AXClient interface { // Tasks GetTask(ctx context.Context, in *GetTaskRequest, opts ...grpc.CallOption) (*Task, error) ListTasks(ctx context.Context, in *ListTasksRequest, opts ...grpc.CallOption) (*ListTasksResponse, error) - UpdateTask(ctx context.Context, in *UpdateTaskRequest, opts ...grpc.CallOption) (*Task, error) + CreateTask(ctx context.Context, in *CreateTaskRequest, opts ...grpc.CallOption) (*Task, error) DeleteTask(ctx context.Context, in *DeleteTaskRequest, opts ...grpc.CallOption) (*DeleteTaskResponse, error) SuspendTask(ctx context.Context, in *SuspendTaskRequest, opts ...grpc.CallOption) (*Task, error) ResumeTask(ctx context.Context, in *ResumeTaskRequest, opts ...grpc.CallOption) (*Task, error) @@ -104,10 +104,10 @@ func (c *aXClient) ListTasks(ctx context.Context, in *ListTasksRequest, opts ... return out, nil } -func (c *aXClient) UpdateTask(ctx context.Context, in *UpdateTaskRequest, opts ...grpc.CallOption) (*Task, error) { +func (c *aXClient) CreateTask(ctx context.Context, in *CreateTaskRequest, opts ...grpc.CallOption) (*Task, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(Task) - err := c.cc.Invoke(ctx, AX_UpdateTask_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, AX_CreateTask_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -252,7 +252,7 @@ type AXServer interface { // Tasks GetTask(context.Context, *GetTaskRequest) (*Task, error) ListTasks(context.Context, *ListTasksRequest) (*ListTasksResponse, error) - UpdateTask(context.Context, *UpdateTaskRequest) (*Task, error) + CreateTask(context.Context, *CreateTaskRequest) (*Task, error) DeleteTask(context.Context, *DeleteTaskRequest) (*DeleteTaskResponse, error) SuspendTask(context.Context, *SuspendTaskRequest) (*Task, error) ResumeTask(context.Context, *ResumeTaskRequest) (*Task, error) @@ -278,49 +278,49 @@ type AXServer interface { type UnimplementedAXServer struct{} func (UnimplementedAXServer) GetTask(context.Context, *GetTaskRequest) (*Task, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetTask not implemented") + return nil, status.Error(codes.Unimplemented, "method GetTask not implemented") } func (UnimplementedAXServer) ListTasks(context.Context, *ListTasksRequest) (*ListTasksResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListTasks not implemented") + return nil, status.Error(codes.Unimplemented, "method ListTasks not implemented") } -func (UnimplementedAXServer) UpdateTask(context.Context, *UpdateTaskRequest) (*Task, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateTask not implemented") +func (UnimplementedAXServer) CreateTask(context.Context, *CreateTaskRequest) (*Task, error) { + return nil, status.Error(codes.Unimplemented, "method CreateTask not implemented") } func (UnimplementedAXServer) DeleteTask(context.Context, *DeleteTaskRequest) (*DeleteTaskResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteTask not implemented") + return nil, status.Error(codes.Unimplemented, "method DeleteTask not implemented") } func (UnimplementedAXServer) SuspendTask(context.Context, *SuspendTaskRequest) (*Task, error) { - return nil, status.Errorf(codes.Unimplemented, "method SuspendTask not implemented") + return nil, status.Error(codes.Unimplemented, "method SuspendTask not implemented") } func (UnimplementedAXServer) ResumeTask(context.Context, *ResumeTaskRequest) (*Task, error) { - return nil, status.Errorf(codes.Unimplemented, "method ResumeTask not implemented") + return nil, status.Error(codes.Unimplemented, "method ResumeTask not implemented") } func (UnimplementedAXServer) WatchTask(*WatchTaskRequest, grpc.ServerStreamingServer[WatchTaskResponse]) error { - return status.Errorf(codes.Unimplemented, "method WatchTask not implemented") + return status.Error(codes.Unimplemented, "method WatchTask not implemented") } func (UnimplementedAXServer) GetWorkspace(context.Context, *GetWorkspaceRequest) (*Workspace, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetWorkspace not implemented") + return nil, status.Error(codes.Unimplemented, "method GetWorkspace not implemented") } func (UnimplementedAXServer) ListWorkspaces(context.Context, *ListWorkspacesRequest) (*ListWorkspacesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListWorkspaces not implemented") + return nil, status.Error(codes.Unimplemented, "method ListWorkspaces not implemented") } func (UnimplementedAXServer) UpdateWorkspace(context.Context, *UpdateWorkspaceRequest) (*Workspace, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateWorkspace not implemented") + return nil, status.Error(codes.Unimplemented, "method UpdateWorkspace not implemented") } func (UnimplementedAXServer) DeleteWorkspace(context.Context, *DeleteWorkspaceRequest) (*DeleteWorkspaceResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteWorkspace not implemented") + return nil, status.Error(codes.Unimplemented, "method DeleteWorkspace not implemented") } func (UnimplementedAXServer) GetModel(context.Context, *GetModelRequest) (*Model, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetModel not implemented") + return nil, status.Error(codes.Unimplemented, "method GetModel not implemented") } func (UnimplementedAXServer) ListModels(context.Context, *ListModelsRequest) (*ListModelsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListModels not implemented") + return nil, status.Error(codes.Unimplemented, "method ListModels not implemented") } func (UnimplementedAXServer) UpdateModel(context.Context, *UpdateModelRequest) (*Model, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateModel not implemented") + return nil, status.Error(codes.Unimplemented, "method UpdateModel not implemented") } func (UnimplementedAXServer) DeleteModel(context.Context, *DeleteModelRequest) (*DeleteModelResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteModel not implemented") + return nil, status.Error(codes.Unimplemented, "method DeleteModel not implemented") } func (UnimplementedAXServer) mustEmbedUnimplementedAXServer() {} func (UnimplementedAXServer) testEmbeddedByValue() {} @@ -333,7 +333,7 @@ type UnsafeAXServer interface { } func RegisterAXServer(s grpc.ServiceRegistrar, srv AXServer) { - // If the following call pancis, it indicates UnimplementedAXServer was + // If the following call panics, it indicates UnimplementedAXServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. @@ -379,20 +379,20 @@ func _AX_ListTasks_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } -func _AX_UpdateTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UpdateTaskRequest) +func _AX_CreateTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateTaskRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(AXServer).UpdateTask(ctx, in) + return srv.(AXServer).CreateTask(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: AX_UpdateTask_FullMethodName, + FullMethod: AX_CreateTask_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AXServer).UpdateTask(ctx, req.(*UpdateTaskRequest)) + return srv.(AXServer).CreateTask(ctx, req.(*CreateTaskRequest)) } return interceptor(ctx, in, info, handler) } @@ -622,8 +622,8 @@ var AX_ServiceDesc = grpc.ServiceDesc{ Handler: _AX_ListTasks_Handler, }, { - MethodName: "UpdateTask", - Handler: _AX_UpdateTask_Handler, + MethodName: "CreateTask", + Handler: _AX_CreateTask_Handler, }, { MethodName: "DeleteTask", diff --git a/pkg/apis/v1alpha1/types_test.go b/pkg/apis/v1alpha1/types_test.go index 99ab8bd0..0cf1ab01 100644 --- a/pkg/apis/v1alpha1/types_test.go +++ b/pkg/apis/v1alpha1/types_test.go @@ -38,7 +38,6 @@ func fullTask() *v1alpha1.Task { CreationTimestamp: timestamppb.New(time.Date(2026, 9, 19, 12, 0, 0, 0, time.UTC)), }, Spec: &v1alpha1.TaskSpec{ - Suspend: true, Image: "example.com/img:1", Command: []string{"sh", "-c", "true"}, Env: []*v1alpha1.EnvVar{{Name: "A", Value: "1"}},