diff --git a/CHANGELOG.md b/CHANGELOG.md index 71320ac..f90ac27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,39 @@ All notable changes to this project are documented here. Versions follow the `vMAJOR.MINOR.PATCH` git tags that drive the release pipeline. +## v0.2.0 + +Supported Easypanel versions: **2.32.0 .. 2.33.1**, unchanged from v0.1.0. + +### Features + +- New RPC `UpdateComposeSource` replaces the compose content of an existing + compose service and redeploys it. `DeployCompose` calls the panel's + `createService` first, so it fails with `Service already exists.` on a service + that is already there, leaving no way to update a live stack over gRPC. The new + RPC runs the same gate as `DeployCompose` (invalid YAML and `network_mode: host` + rejected, host `ports:` stripped, `expose:` kept), maps a missing or + wrong-typed service to `NotFound`, and accepts `skip_deploy` to store content + without deploying so several edits can be batched into one deploy. + +### Fixes + +- Stop sending `composeFile` to `services.compose.updateSourceInline`. The panel's + schema accepts only `projectName`, `serviceName` and `content`, and silently + dropped the extra field. Affected `DeployCompose` and the CLI. +- `services set-source-inline` now takes 3 arguments + (`[project] [service] [compose-content]`). The old 4-argument form is still + accepted and warns that the `compose-file` argument is ignored. + +### Internal + +- `easypanel.IsNotFound` classifies the panel's `NOT_FOUND`, which it returns both + for a missing service and for one whose type does not match the route namespace. +- Unit tests cover the new RPC's field payload, sanitizing, `skip_deploy`, + `NotFound` mapping, input validation and deploy failures. New live test + `TestGRPC_UpdateComposeSourceE2E` also asserts that `DeployCompose` still + refuses an existing service, which is the gap this RPC fills. + ## v0.1.0 Supported Easypanel versions: **2.32.0 .. 2.33.1**, both bounds backed by pinned diff --git a/README.md b/README.md index 0798eb2..d7b9d99 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ A Go toolkit for managing [Easypanel](https://easypanel.io) deployments — both ┌──────────────────▼──────────────────────────────────┐ │ gRPC PaaS Server (cmd/grpc-server) │ │ • Auth interceptor (constant-time token compare) │ -│ • 16 RPC methods │ +│ • 17 RPC methods │ │ • Compose port sanitization │ │ • Auto-domain provisioning │ └──────────────────┬──────────────────────────────────┘ @@ -31,7 +31,7 @@ A Go toolkit for managing [Easypanel](https://easypanel.io) deployments — both - **CLI** — Direct Easypanel tRPC control (projects, services, domains, users, certs, settings) - **gRPC Server** — Multi-tenant PaaS adapter with bearer token authentication - **Container Deployments** — Deploy Docker images with auto-assigned domains -- **Compose Stacks** — Deploy docker-compose with per-service domain routing (ports auto-stripped for security) +- **Compose Stacks** — Deploy docker-compose with per-service domain routing (ports auto-stripped for security), and replace the content of a live stack in place - **Domain Management** — Default subdomains + custom domains with HTTPS - **Lifecycle Control** — Start, stop, restart, scale, update env/resources - **Resource Limits** — CPU and memory constraints per service @@ -118,7 +118,7 @@ export EASYPANEL_ENDPOINT EASYPANEL_API_KEY ./deploy-everything services set-dockerfile '' # Compose sources (save, then automatically redeploy) -./deploy-everything services set-source-inline docker-compose.yml '' +./deploy-everything services set-source-inline '' ./deploy-everything services set-source-git-compose docker-compose.yml [--root-path /] # Logs @@ -180,7 +180,8 @@ Tokens are configured via `GRPC_AUTH_TOKENS` (comma-separated). Tokens grant pan | Method | Description | |--------|-------------| | `DeployContainer` | Deploy Docker image → create service + set image + env + deploy + auto-domain | -| `DeployCompose` | Deploy docker-compose stack (strips `ports:`, routes via `composeService`) | +| `DeployCompose` | Create and deploy a docker-compose stack (strips `ports:`, routes via `composeService`). Fails if the service already exists | +| `UpdateComposeSource` | Replace the compose content of an existing compose service, then redeploy. Set `skip_deploy` to store without deploying | | `DestroyService` | Remove service and all associated domains | | `GetServiceStatus` | Service config (name, type, image, env, domains, deploy URL) plus runtime state (`status`, running containers, compose sub-services). Env values are redacted unless `include_env` is set | | `ListServices` | All services in a project | @@ -233,6 +234,33 @@ grpcurl -plaintext -H "authorization: your-token" -d '{ }' localhost:50051 paas.PaaS/DeployCompose ``` +#### Update an existing compose stack + +`DeployCompose` creates: it calls the panel's `createService` first, so it fails with +`create compose: [BAD_REQUEST] Service already exists.` on a service that is already +there. Use `UpdateComposeSource` to replace the content of a live stack. + +```bash +grpcurl -plaintext -H "authorization: your-token" -d '{ + "project": "myproject", + "service": "stack", + "composeContent": "services:\n web:\n image: wordpress:6.5\n expose:\n - \"80\"\n" +}' localhost:50051 paas.PaaS/UpdateComposeSource +``` + +```json +{ + "deployed": true, + "status": "deploying" +} +``` + +The content fully replaces what was stored, and goes through the same gate as +`DeployCompose`: invalid YAML and `network_mode: host` are rejected, host-published +`ports:` are stripped, `expose:` is kept. Set `"skipDeploy": true` to store the +content without redeploying, then deploy once after a batch of edits. A service that +does not exist, or exists under another type, returns `NotFound`. + #### Add a custom domain ```bash @@ -506,11 +534,11 @@ One `Dockerfile`, two final stages, both distroless + static (`CGO_ENABLED=0`), ```bash # Run the gRPC server docker run --rm -p 50051:50051 --env-file .env \ - ghcr.io/igun997/deploy-everything:0.1.0 + ghcr.io/igun997/deploy-everything:0.2.0 # Run a CLI command docker run --rm --env-file .env \ - ghcr.io/igun997/deploy-everything-cli:0.1.0 projects list + ghcr.io/igun997/deploy-everything-cli:0.2.0 projects list # Bleeding edge (current master) docker run --rm --env-file .env \ @@ -531,13 +559,13 @@ docker run --rm --env-file .env \ | Git event | Image tags | |-----------|-----------| | push/merge to `master` | `dev`, `dev-` | -| tag `v0.1.0` | `0.1.0`, `0.1`, `0`, `latest` | +| tag `v0.2.0` | `0.2.0`, `0.2`, `0`, `latest` | | tag `v1.2.3` | `1.2.3`, `1.2`, `1`, `latest` | | pre-release tag `v1.2.3-rc1` | `1.2.3-rc1` only (no `latest`, no `1.2`/`1`) | So `:dev` always points at the current `master`, `:latest` always points at the newest stable release. -The leading `v` is stripped from image tags: git tag `v0.1.0` produces image tag `0.1.0`. The binaries still report the full `v0.1.0` from `version`. +The leading `v` is stripped from image tags: git tag `v0.2.0` produces image tag `0.2.0`. The binaries still report the full `v0.2.0` from `version`. ### Cutting a release diff --git a/cmd/services.go b/cmd/services.go index e528643..f2d8696 100644 --- a/cmd/services.go +++ b/cmd/services.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "os" "sort" "strings" @@ -678,26 +679,37 @@ func rawJSONText(raw json.RawMessage) string { // --- Compose-specific --- var servicesSetSourceInlineCmd = &cobra.Command{ - Use: "set-source-inline [project] [service] [compose-file] [compose-content]", + Use: "set-source-inline [project] [service] [compose-content]", Short: "Set inline compose content (compose type)", - Args: cobra.ExactArgs(4), + Long: "Set inline compose content (compose type).\n\n" + + "A 4-argument form [project] [service] [compose-file] [compose-content] is still\n" + + "accepted for compatibility. The panel schema has no compose-file field, so that\n" + + "argument is ignored.", + Args: cobra.RangeArgs(3, 4), RunE: func(cmd *cobra.Command, args []string) error { + project, service := args[0], args[1] + content := args[2] + if len(args) == 4 { + // Legacy positional compose-file, dropped by the panel's zod schema. + content = args[3] + fmt.Fprintln(os.Stderr, "warning: the compose-file argument is ignored; the panel accepts only projectName, serviceName and content") + } + c := newPanelClient() input := map[string]any{ - "projectName": args[0], - "serviceName": args[1], - "composeFile": args[2], + "projectName": project, + "serviceName": service, // Panel schema calls this field "content", not "composeContent". - "content": args[3], + "content": content, } err := c.call(context.Background(), "/api/trpc/services.compose.updateSourceInline", input, nil) if err != nil { return err } - if err := redeployAfterConfig(c, args[0], args[1], "compose"); err != nil { + if err := redeployAfterConfig(c, project, service, "compose"); err != nil { return fmt.Errorf("apply inline source: %w", err) } - fmt.Printf("Inline source set and deployed: %s/%s\n", args[0], args[1]) + fmt.Printf("Inline source set and deployed: %s/%s\n", project, service) return nil }, } diff --git a/docs/deployment-guide.md b/docs/deployment-guide.md index 155f797..792e339 100644 --- a/docs/deployment-guide.md +++ b/docs/deployment-guide.md @@ -5,7 +5,7 @@ This guide covers deploying the `deploy-everything` gRPC server and using both i - **gRPC API** — deploy prebuilt container images or complete Compose stacks. - **CLI** — deploy images, inline Dockerfiles, Git/GitHub sources, and Compose sources. -Examples use release `0.1.0`. +Examples use release `0.2.0`. Supported Easypanel versions: `2.32.0` .. `2.33.1`. Check what you are pointed at with `deploy-everything settings panel-version`. @@ -61,21 +61,21 @@ The gRPC deployment RPCs create services inside projects; they do not create pro ### Docker ```bash -docker pull ghcr.io/igun997/deploy-everything:0.1.0 +docker pull ghcr.io/igun997/deploy-everything:0.2.0 docker run -d \ --name deploy-everything \ --restart unless-stopped \ -p 50051:50051 \ --env-file .env \ - ghcr.io/igun997/deploy-everything:0.1.0 + ghcr.io/igun997/deploy-everything:0.2.0 ``` Verify: ```bash docker logs deploy-everything -docker run --rm ghcr.io/igun997/deploy-everything:0.1.0 version +docker run --rm ghcr.io/igun997/deploy-everything:0.2.0 version ``` ### Docker Compose @@ -84,7 +84,7 @@ docker run --rm ghcr.io/igun997/deploy-everything:0.1.0 version # compose.grpc-server.yml services: deploy-everything: - image: ghcr.io/igun997/deploy-everything:0.1.0 + image: ghcr.io/igun997/deploy-everything:0.2.0 restart: unless-stopped ports: - "50051:50051" @@ -240,6 +240,48 @@ Without `customDomain`, generated host format is: {project}-{service}-{composeService}.{DEFAULT_DOMAIN} ``` +### Update an existing Compose stack + +`DeployCompose` creates. It calls the panel's `createService` first, so a second call +for the same service fails: + +```text +create compose: [BAD_REQUEST] Service already exists. +``` + +Use `UpdateComposeSource` to replace the content of a stack that is already running: + +```bash +jq -n --rawfile compose docker-compose.yml '{ + project: "demo", + service: "whoami-stack", + composeContent: $compose +}' > /tmp/update-compose.json + +paas_call UpdateComposeSource < /tmp/update-compose.json +``` + +```json +{ + "deployed": true, + "status": "deploying" +} +``` + +| Field | Meaning | +|-------|---------| +| `composeContent` | Full replacement. Not merged with the stored content | +| `skipDeploy` | Store the content without redeploying, to batch several edits | +| `deployed` | `false` when `skipDeploy` was set | + +The Compose rules above still apply: invalid YAML and `network_mode: host` are +rejected, host `ports:` are stripped, `expose:` survives. A service that does not +exist, or exists under a different type, returns `NotFound`. + +Domains are not touched by this RPC. Use `AddDomain` / `RemoveDomain` for routing +changes, and note that adding a domain to a Compose stack needs a redeploy to take +effect. + ### Multi-service WordPress + MySQL + Adminer ```yaml @@ -570,14 +612,14 @@ Use the release binary: ```bash # Download archive from: -# https://github.com/igun997/deploy-everything/releases/tag/v0.1.0 +# https://github.com/igun997/deploy-everything/releases/tag/v0.2.0 ``` Or run the CLI image: ```bash docker run --rm --env-file .env \ - ghcr.io/igun997/deploy-everything-cli:0.1.0 version + ghcr.io/igun997/deploy-everything-cli:0.2.0 version ``` For local commands: @@ -592,7 +634,7 @@ Examples below use `$CLI`. If using Docker for every command, replace `$CLI` wit ```bash docker run --rm --env-file .env \ - ghcr.io/igun997/deploy-everything-cli:0.1.0 + ghcr.io/igun997/deploy-everything-cli:0.2.0 ``` ## 9. CLI: normal app deployment cases @@ -687,7 +729,7 @@ services: ```bash $CLI services create demo stack compose -$CLI services set-source-inline demo stack docker-compose.yml "$(cat docker-compose.yml)" +$CLI services set-source-inline demo stack "$(cat docker-compose.yml)" $CLI domains create demo stack stack.example.com \ --type compose \ --compose-service web \ @@ -697,6 +739,10 @@ $CLI domains create demo stack stack.example.com \ Both source and domain commands automatically redeploy. Direct CLI Compose source is sent to Easypanel as written, so use `expose` rather than host `ports`. +Re-running `set-source-inline` on the same service replaces the stored content, so +this is also the update path. The gRPC equivalent is +[`UpdateComposeSource`](#update-an-existing-compose-stack). + ### Compose from Git ```bash @@ -883,7 +929,7 @@ Send exact token configured in `GRPC_AUTH_TOKENS`: ```bash ./deploy-everything version ./grpc-server version -docker run --rm ghcr.io/igun997/deploy-everything-cli:0.1.0 version +docker run --rm ghcr.io/igun997/deploy-everything-cli:0.2.0 version # Easypanel version + supported range ./deploy-everything settings panel-version diff --git a/grpc_e2e_test.go b/grpc_e2e_test.go index bc500e0..8ddc1e2 100644 --- a/grpc_e2e_test.go +++ b/grpc_e2e_test.go @@ -548,3 +548,127 @@ func TestGRPC_RuntimeStatusAndLogs(t *testing.T) { } t.Log(" ✓ env redacted by default, returned with include_env") } + +// TestGRPC_UpdateComposeSourceE2E covers the gap DeployCompose leaves: replacing +// the compose content of a service that already exists. DeployCompose calls +// createService first, which the panel rejects with "Service already exists." +func TestGRPC_UpdateComposeSourceE2E(t *testing.T) { + client, cleanup := startTestServer(t) + defer cleanup() + + ctx := authCtx() + project := "pods" + service := "update-src-e2e" + + client.DestroyService(ctx, &pb.DestroyServiceRequest{ + Project: project, Service: service, ServiceType: "compose", + }) + defer client.DestroyService(ctx, &pb.DestroyServiceRequest{ + Project: project, Service: service, ServiceType: "compose", + }) + + // A missing service must not look like a transport failure. + t.Log("Step 1: UpdateComposeSource on a service that does not exist") + _, err := client.UpdateComposeSource(ctx, &pb.UpdateComposeSourceRequest{ + Project: project, Service: service, + ComposeContent: "services:\n web:\n image: nginx:alpine\n", + }) + if grpcstatus.Code(err) != codes.NotFound { + t.Fatalf("want NotFound before the service exists, got %v", err) + } + t.Logf(" ✓ %v", err) + + t.Log("Step 2: DeployCompose to create it") + if _, err := client.DeployCompose(ctx, &pb.DeployComposeRequest{ + Project: project, Service: service, + ComposeContent: "services:\n web:\n image: nginx:alpine\n expose:\n - \"80\"\n", + }); err != nil { + t.Fatalf("DeployCompose: %v", err) + } + t.Log(" ✓ created") + + // DeployCompose cannot be reused to update: prove the failure this RPC fixes. + t.Log("Step 3: DeployCompose again must fail on the existing service") + if _, err := client.DeployCompose(ctx, &pb.DeployComposeRequest{ + Project: project, Service: service, + ComposeContent: "services:\n web:\n image: nginx:alpine\n", + }); err == nil { + t.Fatal("want DeployCompose to reject an existing service") + } else if !strings.Contains(err.Error(), "already exists") { + t.Fatalf("want \"already exists\", got %v", err) + } + t.Log(" ✓ rejected as expected") + + // Host ports must still be stripped, expose kept, content replaced verbatim. + updated := `services: + web: + image: httpd:alpine + ports: + - "8080:80" + expose: + - "80" + environment: + UPDATED_MARKER: update-src-e2e-ok +` + t.Log("Step 4: UpdateComposeSource replaces the content") + resp, err := client.UpdateComposeSource(ctx, &pb.UpdateComposeSourceRequest{ + Project: project, Service: service, ComposeContent: updated, + }) + if err != nil { + t.Fatalf("UpdateComposeSource: %v", err) + } + if !resp.Deployed { + t.Errorf("want deployed=true, got %v (status=%q)", resp.Deployed, resp.Status) + } + t.Logf(" ✓ deployed=%v status=%s", resp.Deployed, resp.Status) + + // GetServiceStatus does not expose compose source, so read it from the panel. + t.Log("Step 5: verify stored content") + stored := composeSource(t, project, service) + if !strings.Contains(stored, "update-src-e2e-ok") { + t.Errorf(" ✗ new content not stored, source=%q", stored) + } + if !strings.Contains(stored, "httpd:alpine") { + t.Errorf(" ✗ image not replaced, source=%q", stored) + } + if strings.Contains(stored, "8080:80") { + t.Errorf(" ✗ host ports survived sanitizing, source=%q", stored) + } + t.Log(" ✓ content replaced, host ports stripped") + + t.Log("Step 6: skipDeploy stores without deploying") + resp, err = client.UpdateComposeSource(ctx, &pb.UpdateComposeSourceRequest{ + Project: project, Service: service, + ComposeContent: "services:\n web:\n image: nginx:alpine\n expose:\n - \"80\"\n", + SkipDeploy: true, + }) + if err != nil { + t.Fatalf("UpdateComposeSource(skipDeploy): %v", err) + } + if resp.Deployed || resp.Status != "stored" { + t.Errorf("want deployed=false status=stored, got %v/%q", resp.Deployed, resp.Status) + } + stored = composeSource(t, project, service) + if !strings.Contains(stored, "nginx:alpine") || strings.Contains(stored, "httpd:alpine") { + t.Errorf("skipDeploy did not persist the replacement source: %q", stored) + } + t.Log(" ✓ stored without deploy") +} + +// composeSource reads the compose content the panel has stored for a service. +func composeSource(t *testing.T, project, service string) string { + t.Helper() + ep := easypanel.NewClient(os.Getenv("EASYPANEL_ENDPOINT"), os.Getenv("EASYPANEL_API_KEY")) + var resp easypanel.Response[struct { + Source struct { + Content string `json:"content"` + } `json:"source"` + }] + if err := ep.Call(context.Background(), easypanel.ComposeRoute(easypanel.ProcInspectService), map[string]string{ + "projectName": project, + "serviceName": service, + }, &resp); err != nil { + t.Fatalf("inspect compose source: %v", err) + } + return resp.JSON.Source.Content +} diff --git a/internal/easypanel/client.go b/internal/easypanel/client.go index 9de13f7..7d7c897 100644 --- a/internal/easypanel/client.go +++ b/internal/easypanel/client.go @@ -106,6 +106,17 @@ func IsLogStoreUnreachable(err error) bool { return false } +// IsNotFound reports whether err is the panel's NOT_FOUND. The panel returns it +// both for a missing service and for a service of a different type than the +// route's namespace, since each type only inspects its own services. +func IsNotFound(err error) bool { + var apiErr *APIError + if !errors.As(err, &apiErr) { + return false + } + return apiErr.Code == "NOT_FOUND" || apiErr.Status == 404 +} + // trpcErrorEnvelope is how the panel reports errors: nested under "json", with // zod field errors under data.zodErrors. type trpcErrorEnvelope struct { diff --git a/internal/easypanel/version_test.go b/internal/easypanel/version_test.go index bc8d190..49430e4 100644 --- a/internal/easypanel/version_test.go +++ b/internal/easypanel/version_test.go @@ -109,3 +109,21 @@ func TestIsLogStoreUnreachable(t *testing.T) { t.Error("plain errors must not be classified as panel log store failures") } } + +func TestIsNotFound(t *testing.T) { + // The panel answers NOT_FOUND for a missing service and for one whose type + // does not match the route namespace. + if !IsNotFound(error(&APIError{Code: "NOT_FOUND", Status: 404, Message: "Service not found."})) { + t.Error("want NOT_FOUND classified as not found") + } + // Status alone is enough: some proxies drop the code. + if !IsNotFound(error(&APIError{Status: 404, Message: "Service not found."})) { + t.Error("want status 404 classified as not found") + } + if IsNotFound(error(&APIError{Code: "BAD_REQUEST", Status: 400, Message: "Service already exists."})) { + t.Error("did not expect BAD_REQUEST classified as not found") + } + if IsNotFound(errors.New("Service not found.")) { + t.Error("plain errors must not be classified as panel NOT_FOUND") + } +} diff --git a/internal/server/paas.go b/internal/server/paas.go index a10dfdf..1af136b 100644 --- a/internal/server/paas.go +++ b/internal/server/paas.go @@ -216,7 +216,6 @@ func (s *PaaSServer) DeployCompose(ctx context.Context, req *pb.DeployComposeReq err = s.ep.Call(ctx, easypanel.ComposeRoute(easypanel.ProcUpdateSourceInline), map[string]any{ "projectName": req.Project, "serviceName": req.Service, - "composeFile": "docker-compose.yml", "content": content, }, nil) if err != nil { @@ -290,6 +289,53 @@ func (s *PaaSServer) DeployCompose(ctx context.Context, req *pb.DeployComposeReq }, nil } +// UpdateComposeSource replaces the compose content of a service that already +// exists. DeployCompose cannot do this: it calls createService first, which the +// panel rejects with "Service already exists." before any content is written. +func (s *PaaSServer) UpdateComposeSource(ctx context.Context, req *pb.UpdateComposeSourceRequest) (*pb.UpdateComposeSourceResponse, error) { + if req.Project == "" || req.Service == "" { + return nil, status.Error(codes.InvalidArgument, "project and service are required") + } + if strings.TrimSpace(req.ComposeContent) == "" { + return nil, status.Error(codes.InvalidArgument, "composeContent is required") + } + + // Same gate as DeployCompose: reject invalid YAML and host networking, and + // drop host-published ports, before anything reaches the panel. + content, err := sanitizeCompose(req.ComposeContent) + if err != nil { + return nil, status.Errorf(codes.InvalidArgument, "invalid compose YAML: %v", err) + } + + err = s.ep.Call(ctx, easypanel.ComposeRoute(easypanel.ProcUpdateSourceInline), map[string]any{ + "projectName": req.Project, + "serviceName": req.Service, + "content": content, + }, nil) + if err != nil { + // The panel answers NOT_FOUND both for a missing service and for one that + // is not a compose service, since each type only sees its own. + if easypanel.IsNotFound(err) { + return nil, status.Errorf(codes.NotFound, + "no compose service %q in project %q: use DeployCompose to create it, and check the service type if it already exists", + req.Service, req.Project) + } + return nil, fmt.Errorf("set compose: %w", err) + } + + // Stored content only takes effect on deploy. Callers batching several edits + // can skip it and deploy once at the end. + if req.SkipDeploy { + return &pb.UpdateComposeSourceResponse{Deployed: false, Status: "stored"}, nil + } + + if err := s.redeployCompose(ctx, req.Project, req.Service); err != nil { + return nil, fmt.Errorf("deploy: %w", err) + } + + return &pb.UpdateComposeSourceResponse{Deployed: true, Status: "deploying"}, nil +} + func (s *PaaSServer) DestroyService(ctx context.Context, req *pb.DestroyServiceRequest) (*pb.DestroyServiceResponse, error) { svcType := req.ServiceType if svcType == "" { diff --git a/internal/server/panel_fake_test.go b/internal/server/panel_fake_test.go index 1611168..1b81c73 100644 --- a/internal/server/panel_fake_test.go +++ b/internal/server/panel_fake_test.go @@ -5,6 +5,7 @@ import ( "io" "net/http" "net/http/httptest" + "strconv" "strings" "sync" "testing" @@ -56,9 +57,13 @@ func (p *fakePanel) handle(w http.ResponseWriter, r *http.Request) { return } if strings.HasPrefix(resp, "!") { - // "! " returns an error response. + // "! " returns an error response with that HTTP status. parts := strings.SplitN(strings.TrimPrefix(resp, "!"), " ", 2) - w.WriteHeader(http.StatusBadRequest) + code, err := strconv.Atoi(parts[0]) + if err != nil { + code = http.StatusBadRequest + } + w.WriteHeader(code) if len(parts) == 2 { _, _ = w.Write([]byte(parts[1])) } diff --git a/internal/server/updatecomposesource_test.go b/internal/server/updatecomposesource_test.go new file mode 100644 index 0000000..3f50c4f --- /dev/null +++ b/internal/server/updatecomposesource_test.go @@ -0,0 +1,164 @@ +package server + +import ( + "context" + "strings" + "testing" + + "github.com/igun997/deploy-everything/internal/easypanel" + pb "github.com/igun997/deploy-everything/proto" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var ( + routeComposeUpdateSource = easypanel.ComposeRoute(easypanel.ProcUpdateSourceInline) + routeComposeDeploy = easypanel.ComposeRoute(easypanel.ProcDeployService) +) + +const composeWithHostPorts = `services: + agent: + image: nginx + ports: + - "8080:80" + expose: + - "8642" +` + +func okPanel(t *testing.T) *fakePanel { + t.Helper() + return newFakePanel(t, map[string]string{ + routeComposeUpdateSource: `{"json":null}`, + routeComposeDeploy: `{"json":null}`, + }) +} + +func TestUpdateComposeSourceSendsOnlyPanelFieldsAndDeploys(t *testing.T) { + panel := okPanel(t) + + resp, err := panel.newServer().UpdateComposeSource(context.Background(), &pb.UpdateComposeSourceRequest{ + Project: "pods", Service: "hermes-a1", ComposeContent: composeWithHostPorts, + }) + if err != nil { + t.Fatalf("UpdateComposeSource: %v", err) + } + if !resp.Deployed || resp.Status != "deploying" { + t.Errorf("want deployed=true status=deploying, got %v/%q", resp.Deployed, resp.Status) + } + + in := panel.input(routeComposeUpdateSource, 0) + // The panel's zod schema accepts only these three fields. + if len(in) != 3 { + t.Errorf("want exactly 3 input fields, got %d: %v", len(in), in) + } + if _, ok := in["composeFile"]; ok { + t.Error("composeFile is not in the panel schema and must not be sent") + } + if in["projectName"] != "pods" || in["serviceName"] != "hermes-a1" { + t.Errorf("wrong identifiers: %v", in) + } + + content, _ := in["content"].(string) + if strings.Contains(content, "8080:80") { + t.Error("host-published ports must be stripped before reaching the panel") + } + if !strings.Contains(content, "8642") { + t.Error("expose must survive sanitizing") + } + + if panel.callCount(routeComposeDeploy) != 1 { + t.Errorf("want 1 deploy call, got %d", panel.callCount(routeComposeDeploy)) + } +} + +func TestUpdateComposeSourceSkipDeploy(t *testing.T) { + panel := okPanel(t) + + resp, err := panel.newServer().UpdateComposeSource(context.Background(), &pb.UpdateComposeSourceRequest{ + Project: "pods", Service: "hermes-a1", ComposeContent: composeWithHostPorts, SkipDeploy: true, + }) + if err != nil { + t.Fatalf("UpdateComposeSource: %v", err) + } + if resp.Deployed || resp.Status != "stored" { + t.Errorf("want deployed=false status=stored, got %v/%q", resp.Deployed, resp.Status) + } + if panel.callCount(routeComposeUpdateSource) != 1 { + t.Error("content must still be written when the deploy is skipped") + } + if got := panel.callCount(routeComposeDeploy); got != 0 { + t.Errorf("skipDeploy must not deploy, got %d deploy calls", got) + } +} + +func TestUpdateComposeSourceMapsMissingServiceToNotFound(t *testing.T) { + // The panel answers NOT_FOUND for a missing service and for a service of a + // different type, since each type only inspects its own. + panel := newFakePanel(t, map[string]string{ + routeComposeUpdateSource: `!404 {"json":{"code":"NOT_FOUND","status":404,"message":"Service not found."}}`, + }) + + _, err := panel.newServer().UpdateComposeSource(context.Background(), &pb.UpdateComposeSourceRequest{ + Project: "pods", Service: "ghost", ComposeContent: composeWithHostPorts, + }) + if err == nil { + t.Fatal("want an error for a service that does not exist") + } + if got := status.Code(err); got != codes.NotFound { + t.Errorf("want NotFound, got %s: %v", got, err) + } + if !strings.Contains(err.Error(), "DeployCompose") { + t.Errorf("the error should point at the RPC that creates the service, got %q", err.Error()) + } + if panel.callCount(routeComposeDeploy) != 0 { + t.Error("a failed content write must not be followed by a deploy") + } +} + +func TestUpdateComposeSourceRejectsBadInput(t *testing.T) { + cases := []struct { + name string + req *pb.UpdateComposeSourceRequest + }{ + {"no project", &pb.UpdateComposeSourceRequest{Service: "a", ComposeContent: composeWithHostPorts}}, + {"no service", &pb.UpdateComposeSourceRequest{Project: "p", ComposeContent: composeWithHostPorts}}, + {"empty content", &pb.UpdateComposeSourceRequest{Project: "p", Service: "a", ComposeContent: " \n"}}, + {"not yaml", &pb.UpdateComposeSourceRequest{Project: "p", Service: "a", ComposeContent: "\tnot: [yaml"}}, + {"no services key", &pb.UpdateComposeSourceRequest{Project: "p", Service: "a", ComposeContent: "version: \"3\"\n"}}, + {"host networking", &pb.UpdateComposeSourceRequest{Project: "p", Service: "a", + ComposeContent: "services:\n a:\n image: nginx\n network_mode: host\n"}}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + panel := okPanel(t) + _, err := panel.newServer().UpdateComposeSource(context.Background(), tc.req) + if err == nil { + t.Fatal("want InvalidArgument") + } + if got := status.Code(err); got != codes.InvalidArgument { + t.Errorf("want InvalidArgument, got %s: %v", got, err) + } + if panel.callCount(routeComposeUpdateSource) != 0 { + t.Error("invalid input must be rejected before the panel is called") + } + }) + } +} + +func TestUpdateComposeSourceReportsDeployFailure(t *testing.T) { + panel := newFakePanel(t, map[string]string{ + routeComposeUpdateSource: `{"json":null}`, + routeComposeDeploy: `!400 {"json":{"code":"BAD_REQUEST","status":400,"message":"deploy is already running"}}`, + }) + + _, err := panel.newServer().UpdateComposeSource(context.Background(), &pb.UpdateComposeSourceRequest{ + Project: "pods", Service: "hermes-a1", ComposeContent: composeWithHostPorts, + }) + if err == nil { + t.Fatal("want the deploy failure surfaced") + } + if !strings.Contains(err.Error(), "deploy") { + t.Errorf("want the deploy step named in the error, got %q", err.Error()) + } +} diff --git a/proto/paas.pb.go b/proto/paas.pb.go index 2b7bc58..8e67dba 100644 --- a/proto/paas.pb.go +++ b/proto/paas.pb.go @@ -445,6 +445,126 @@ func (x *DomainMapping) GetPort() int32 { return 0 } +type UpdateComposeSourceRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` + Service string `protobuf:"bytes,2,opt,name=service,proto3" json:"service,omitempty"` + ComposeContent string `protobuf:"bytes,3,opt,name=compose_content,json=composeContent,proto3" json:"compose_content,omitempty"` // full replacement docker-compose.yml content + SkipDeploy bool `protobuf:"varint,4,opt,name=skip_deploy,json=skipDeploy,proto3" json:"skip_deploy,omitempty"` // store the new content without redeploying + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateComposeSourceRequest) Reset() { + *x = UpdateComposeSourceRequest{} + mi := &file_proto_paas_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateComposeSourceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateComposeSourceRequest) ProtoMessage() {} + +func (x *UpdateComposeSourceRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_paas_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateComposeSourceRequest.ProtoReflect.Descriptor instead. +func (*UpdateComposeSourceRequest) Descriptor() ([]byte, []int) { + return file_proto_paas_proto_rawDescGZIP(), []int{6} +} + +func (x *UpdateComposeSourceRequest) GetProject() string { + if x != nil { + return x.Project + } + return "" +} + +func (x *UpdateComposeSourceRequest) GetService() string { + if x != nil { + return x.Service + } + return "" +} + +func (x *UpdateComposeSourceRequest) GetComposeContent() string { + if x != nil { + return x.ComposeContent + } + return "" +} + +func (x *UpdateComposeSourceRequest) GetSkipDeploy() bool { + if x != nil { + return x.SkipDeploy + } + return false +} + +type UpdateComposeSourceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Deployed bool `protobuf:"varint,1,opt,name=deployed,proto3" json:"deployed,omitempty"` // false when skip_deploy was set + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateComposeSourceResponse) Reset() { + *x = UpdateComposeSourceResponse{} + mi := &file_proto_paas_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateComposeSourceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateComposeSourceResponse) ProtoMessage() {} + +func (x *UpdateComposeSourceResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_paas_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateComposeSourceResponse.ProtoReflect.Descriptor instead. +func (*UpdateComposeSourceResponse) Descriptor() ([]byte, []int) { + return file_proto_paas_proto_rawDescGZIP(), []int{7} +} + +func (x *UpdateComposeSourceResponse) GetDeployed() bool { + if x != nil { + return x.Deployed + } + return false +} + +func (x *UpdateComposeSourceResponse) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + type DestroyServiceRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` @@ -456,7 +576,7 @@ type DestroyServiceRequest struct { func (x *DestroyServiceRequest) Reset() { *x = DestroyServiceRequest{} - mi := &file_proto_paas_proto_msgTypes[6] + mi := &file_proto_paas_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -468,7 +588,7 @@ func (x *DestroyServiceRequest) String() string { func (*DestroyServiceRequest) ProtoMessage() {} func (x *DestroyServiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[6] + mi := &file_proto_paas_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -481,7 +601,7 @@ func (x *DestroyServiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DestroyServiceRequest.ProtoReflect.Descriptor instead. func (*DestroyServiceRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{6} + return file_proto_paas_proto_rawDescGZIP(), []int{8} } func (x *DestroyServiceRequest) GetProject() string { @@ -514,7 +634,7 @@ type DestroyServiceResponse struct { func (x *DestroyServiceResponse) Reset() { *x = DestroyServiceResponse{} - mi := &file_proto_paas_proto_msgTypes[7] + mi := &file_proto_paas_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -526,7 +646,7 @@ func (x *DestroyServiceResponse) String() string { func (*DestroyServiceResponse) ProtoMessage() {} func (x *DestroyServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[7] + mi := &file_proto_paas_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -539,7 +659,7 @@ func (x *DestroyServiceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DestroyServiceResponse.ProtoReflect.Descriptor instead. func (*DestroyServiceResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{7} + return file_proto_paas_proto_rawDescGZIP(), []int{9} } func (x *DestroyServiceResponse) GetSuccess() bool { @@ -564,7 +684,7 @@ type GetServiceStatusRequest struct { func (x *GetServiceStatusRequest) Reset() { *x = GetServiceStatusRequest{} - mi := &file_proto_paas_proto_msgTypes[8] + mi := &file_proto_paas_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -576,7 +696,7 @@ func (x *GetServiceStatusRequest) String() string { func (*GetServiceStatusRequest) ProtoMessage() {} func (x *GetServiceStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[8] + mi := &file_proto_paas_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -589,7 +709,7 @@ func (x *GetServiceStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetServiceStatusRequest.ProtoReflect.Descriptor instead. func (*GetServiceStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{8} + return file_proto_paas_proto_rawDescGZIP(), []int{10} } func (x *GetServiceStatusRequest) GetProject() string { @@ -644,7 +764,7 @@ type GetServiceStatusResponse struct { func (x *GetServiceStatusResponse) Reset() { *x = GetServiceStatusResponse{} - mi := &file_proto_paas_proto_msgTypes[9] + mi := &file_proto_paas_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -656,7 +776,7 @@ func (x *GetServiceStatusResponse) String() string { func (*GetServiceStatusResponse) ProtoMessage() {} func (x *GetServiceStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[9] + mi := &file_proto_paas_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -669,7 +789,7 @@ func (x *GetServiceStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetServiceStatusResponse.ProtoReflect.Descriptor instead. func (*GetServiceStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{9} + return file_proto_paas_proto_rawDescGZIP(), []int{11} } func (x *GetServiceStatusResponse) GetName() string { @@ -766,7 +886,7 @@ type ContainerStatus struct { func (x *ContainerStatus) Reset() { *x = ContainerStatus{} - mi := &file_proto_paas_proto_msgTypes[10] + mi := &file_proto_paas_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -778,7 +898,7 @@ func (x *ContainerStatus) String() string { func (*ContainerStatus) ProtoMessage() {} func (x *ContainerStatus) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[10] + mi := &file_proto_paas_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -791,7 +911,7 @@ func (x *ContainerStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use ContainerStatus.ProtoReflect.Descriptor instead. func (*ContainerStatus) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{10} + return file_proto_paas_proto_rawDescGZIP(), []int{12} } func (x *ContainerStatus) GetId() string { @@ -845,7 +965,7 @@ type ListServicesRequest struct { func (x *ListServicesRequest) Reset() { *x = ListServicesRequest{} - mi := &file_proto_paas_proto_msgTypes[11] + mi := &file_proto_paas_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -857,7 +977,7 @@ func (x *ListServicesRequest) String() string { func (*ListServicesRequest) ProtoMessage() {} func (x *ListServicesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[11] + mi := &file_proto_paas_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -870,7 +990,7 @@ func (x *ListServicesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListServicesRequest.ProtoReflect.Descriptor instead. func (*ListServicesRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{11} + return file_proto_paas_proto_rawDescGZIP(), []int{13} } func (x *ListServicesRequest) GetProject() string { @@ -889,7 +1009,7 @@ type ListServicesResponse struct { func (x *ListServicesResponse) Reset() { *x = ListServicesResponse{} - mi := &file_proto_paas_proto_msgTypes[12] + mi := &file_proto_paas_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -901,7 +1021,7 @@ func (x *ListServicesResponse) String() string { func (*ListServicesResponse) ProtoMessage() {} func (x *ListServicesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[12] + mi := &file_proto_paas_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -914,7 +1034,7 @@ func (x *ListServicesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListServicesResponse.ProtoReflect.Descriptor instead. func (*ListServicesResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{12} + return file_proto_paas_proto_rawDescGZIP(), []int{14} } func (x *ListServicesResponse) GetServices() []*ServiceInfo { @@ -936,7 +1056,7 @@ type ServiceInfo struct { func (x *ServiceInfo) Reset() { *x = ServiceInfo{} - mi := &file_proto_paas_proto_msgTypes[13] + mi := &file_proto_paas_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -948,7 +1068,7 @@ func (x *ServiceInfo) String() string { func (*ServiceInfo) ProtoMessage() {} func (x *ServiceInfo) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[13] + mi := &file_proto_paas_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -961,7 +1081,7 @@ func (x *ServiceInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use ServiceInfo.ProtoReflect.Descriptor instead. func (*ServiceInfo) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{13} + return file_proto_paas_proto_rawDescGZIP(), []int{15} } func (x *ServiceInfo) GetName() string { @@ -1008,7 +1128,7 @@ type AddDomainRequest struct { func (x *AddDomainRequest) Reset() { *x = AddDomainRequest{} - mi := &file_proto_paas_proto_msgTypes[14] + mi := &file_proto_paas_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1020,7 +1140,7 @@ func (x *AddDomainRequest) String() string { func (*AddDomainRequest) ProtoMessage() {} func (x *AddDomainRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[14] + mi := &file_proto_paas_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1033,7 +1153,7 @@ func (x *AddDomainRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddDomainRequest.ProtoReflect.Descriptor instead. func (*AddDomainRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{14} + return file_proto_paas_proto_rawDescGZIP(), []int{16} } func (x *AddDomainRequest) GetProject() string { @@ -1095,7 +1215,7 @@ type AddDomainResponse struct { func (x *AddDomainResponse) Reset() { *x = AddDomainResponse{} - mi := &file_proto_paas_proto_msgTypes[15] + mi := &file_proto_paas_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1107,7 +1227,7 @@ func (x *AddDomainResponse) String() string { func (*AddDomainResponse) ProtoMessage() {} func (x *AddDomainResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[15] + mi := &file_proto_paas_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1120,7 +1240,7 @@ func (x *AddDomainResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddDomainResponse.ProtoReflect.Descriptor instead. func (*AddDomainResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{15} + return file_proto_paas_proto_rawDescGZIP(), []int{17} } func (x *AddDomainResponse) GetDomainId() string { @@ -1150,7 +1270,7 @@ type RemoveDomainRequest struct { func (x *RemoveDomainRequest) Reset() { *x = RemoveDomainRequest{} - mi := &file_proto_paas_proto_msgTypes[16] + mi := &file_proto_paas_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1162,7 +1282,7 @@ func (x *RemoveDomainRequest) String() string { func (*RemoveDomainRequest) ProtoMessage() {} func (x *RemoveDomainRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[16] + mi := &file_proto_paas_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1175,7 +1295,7 @@ func (x *RemoveDomainRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveDomainRequest.ProtoReflect.Descriptor instead. func (*RemoveDomainRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{16} + return file_proto_paas_proto_rawDescGZIP(), []int{18} } func (x *RemoveDomainRequest) GetDomainId() string { @@ -1215,7 +1335,7 @@ type RemoveDomainResponse struct { func (x *RemoveDomainResponse) Reset() { *x = RemoveDomainResponse{} - mi := &file_proto_paas_proto_msgTypes[17] + mi := &file_proto_paas_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1227,7 +1347,7 @@ func (x *RemoveDomainResponse) String() string { func (*RemoveDomainResponse) ProtoMessage() {} func (x *RemoveDomainResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[17] + mi := &file_proto_paas_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1240,7 +1360,7 @@ func (x *RemoveDomainResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveDomainResponse.ProtoReflect.Descriptor instead. func (*RemoveDomainResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{17} + return file_proto_paas_proto_rawDescGZIP(), []int{19} } func (x *RemoveDomainResponse) GetSuccess() bool { @@ -1260,7 +1380,7 @@ type ListDomainsRequest struct { func (x *ListDomainsRequest) Reset() { *x = ListDomainsRequest{} - mi := &file_proto_paas_proto_msgTypes[18] + mi := &file_proto_paas_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1272,7 +1392,7 @@ func (x *ListDomainsRequest) String() string { func (*ListDomainsRequest) ProtoMessage() {} func (x *ListDomainsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[18] + mi := &file_proto_paas_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1285,7 +1405,7 @@ func (x *ListDomainsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDomainsRequest.ProtoReflect.Descriptor instead. func (*ListDomainsRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{18} + return file_proto_paas_proto_rawDescGZIP(), []int{20} } func (x *ListDomainsRequest) GetProject() string { @@ -1311,7 +1431,7 @@ type ListDomainsResponse struct { func (x *ListDomainsResponse) Reset() { *x = ListDomainsResponse{} - mi := &file_proto_paas_proto_msgTypes[19] + mi := &file_proto_paas_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1323,7 +1443,7 @@ func (x *ListDomainsResponse) String() string { func (*ListDomainsResponse) ProtoMessage() {} func (x *ListDomainsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[19] + mi := &file_proto_paas_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1336,7 +1456,7 @@ func (x *ListDomainsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDomainsResponse.ProtoReflect.Descriptor instead. func (*ListDomainsResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{19} + return file_proto_paas_proto_rawDescGZIP(), []int{21} } func (x *ListDomainsResponse) GetDomains() []*DomainInfo { @@ -1360,7 +1480,7 @@ type DomainInfo struct { func (x *DomainInfo) Reset() { *x = DomainInfo{} - mi := &file_proto_paas_proto_msgTypes[20] + mi := &file_proto_paas_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1372,7 +1492,7 @@ func (x *DomainInfo) String() string { func (*DomainInfo) ProtoMessage() {} func (x *DomainInfo) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[20] + mi := &file_proto_paas_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1385,7 +1505,7 @@ func (x *DomainInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainInfo.ProtoReflect.Descriptor instead. func (*DomainInfo) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{20} + return file_proto_paas_proto_rawDescGZIP(), []int{22} } func (x *DomainInfo) GetId() string { @@ -1442,7 +1562,7 @@ type UpdateEnvRequest struct { func (x *UpdateEnvRequest) Reset() { *x = UpdateEnvRequest{} - mi := &file_proto_paas_proto_msgTypes[21] + mi := &file_proto_paas_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1454,7 +1574,7 @@ func (x *UpdateEnvRequest) String() string { func (*UpdateEnvRequest) ProtoMessage() {} func (x *UpdateEnvRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[21] + mi := &file_proto_paas_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1467,7 +1587,7 @@ func (x *UpdateEnvRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateEnvRequest.ProtoReflect.Descriptor instead. func (*UpdateEnvRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{21} + return file_proto_paas_proto_rawDescGZIP(), []int{23} } func (x *UpdateEnvRequest) GetProject() string { @@ -1507,7 +1627,7 @@ type UpdateEnvResponse struct { func (x *UpdateEnvResponse) Reset() { *x = UpdateEnvResponse{} - mi := &file_proto_paas_proto_msgTypes[22] + mi := &file_proto_paas_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1519,7 +1639,7 @@ func (x *UpdateEnvResponse) String() string { func (*UpdateEnvResponse) ProtoMessage() {} func (x *UpdateEnvResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[22] + mi := &file_proto_paas_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1532,7 +1652,7 @@ func (x *UpdateEnvResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateEnvResponse.ProtoReflect.Descriptor instead. func (*UpdateEnvResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{22} + return file_proto_paas_proto_rawDescGZIP(), []int{24} } func (x *UpdateEnvResponse) GetSuccess() bool { @@ -1553,7 +1673,7 @@ type RestartServiceRequest struct { func (x *RestartServiceRequest) Reset() { *x = RestartServiceRequest{} - mi := &file_proto_paas_proto_msgTypes[23] + mi := &file_proto_paas_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1565,7 +1685,7 @@ func (x *RestartServiceRequest) String() string { func (*RestartServiceRequest) ProtoMessage() {} func (x *RestartServiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[23] + mi := &file_proto_paas_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1578,7 +1698,7 @@ func (x *RestartServiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RestartServiceRequest.ProtoReflect.Descriptor instead. func (*RestartServiceRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{23} + return file_proto_paas_proto_rawDescGZIP(), []int{25} } func (x *RestartServiceRequest) GetProject() string { @@ -1611,7 +1731,7 @@ type RestartServiceResponse struct { func (x *RestartServiceResponse) Reset() { *x = RestartServiceResponse{} - mi := &file_proto_paas_proto_msgTypes[24] + mi := &file_proto_paas_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1623,7 +1743,7 @@ func (x *RestartServiceResponse) String() string { func (*RestartServiceResponse) ProtoMessage() {} func (x *RestartServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[24] + mi := &file_proto_paas_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1636,7 +1756,7 @@ func (x *RestartServiceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RestartServiceResponse.ProtoReflect.Descriptor instead. func (*RestartServiceResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{24} + return file_proto_paas_proto_rawDescGZIP(), []int{26} } func (x *RestartServiceResponse) GetSuccess() bool { @@ -1657,7 +1777,7 @@ type StopServiceRequest struct { func (x *StopServiceRequest) Reset() { *x = StopServiceRequest{} - mi := &file_proto_paas_proto_msgTypes[25] + mi := &file_proto_paas_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1669,7 +1789,7 @@ func (x *StopServiceRequest) String() string { func (*StopServiceRequest) ProtoMessage() {} func (x *StopServiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[25] + mi := &file_proto_paas_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1682,7 +1802,7 @@ func (x *StopServiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopServiceRequest.ProtoReflect.Descriptor instead. func (*StopServiceRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{25} + return file_proto_paas_proto_rawDescGZIP(), []int{27} } func (x *StopServiceRequest) GetProject() string { @@ -1715,7 +1835,7 @@ type StopServiceResponse struct { func (x *StopServiceResponse) Reset() { *x = StopServiceResponse{} - mi := &file_proto_paas_proto_msgTypes[26] + mi := &file_proto_paas_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1727,7 +1847,7 @@ func (x *StopServiceResponse) String() string { func (*StopServiceResponse) ProtoMessage() {} func (x *StopServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[26] + mi := &file_proto_paas_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1740,7 +1860,7 @@ func (x *StopServiceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StopServiceResponse.ProtoReflect.Descriptor instead. func (*StopServiceResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{26} + return file_proto_paas_proto_rawDescGZIP(), []int{28} } func (x *StopServiceResponse) GetSuccess() bool { @@ -1761,7 +1881,7 @@ type StartServiceRequest struct { func (x *StartServiceRequest) Reset() { *x = StartServiceRequest{} - mi := &file_proto_paas_proto_msgTypes[27] + mi := &file_proto_paas_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1773,7 +1893,7 @@ func (x *StartServiceRequest) String() string { func (*StartServiceRequest) ProtoMessage() {} func (x *StartServiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[27] + mi := &file_proto_paas_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1786,7 +1906,7 @@ func (x *StartServiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartServiceRequest.ProtoReflect.Descriptor instead. func (*StartServiceRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{27} + return file_proto_paas_proto_rawDescGZIP(), []int{29} } func (x *StartServiceRequest) GetProject() string { @@ -1819,7 +1939,7 @@ type StartServiceResponse struct { func (x *StartServiceResponse) Reset() { *x = StartServiceResponse{} - mi := &file_proto_paas_proto_msgTypes[28] + mi := &file_proto_paas_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1831,7 +1951,7 @@ func (x *StartServiceResponse) String() string { func (*StartServiceResponse) ProtoMessage() {} func (x *StartServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[28] + mi := &file_proto_paas_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1844,7 +1964,7 @@ func (x *StartServiceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartServiceResponse.ProtoReflect.Descriptor instead. func (*StartServiceResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{28} + return file_proto_paas_proto_rawDescGZIP(), []int{30} } func (x *StartServiceResponse) GetSuccess() bool { @@ -1881,7 +2001,7 @@ type GetLogsRequest struct { func (x *GetLogsRequest) Reset() { *x = GetLogsRequest{} - mi := &file_proto_paas_proto_msgTypes[29] + mi := &file_proto_paas_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1893,7 +2013,7 @@ func (x *GetLogsRequest) String() string { func (*GetLogsRequest) ProtoMessage() {} func (x *GetLogsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[29] + mi := &file_proto_paas_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1906,7 +2026,7 @@ func (x *GetLogsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLogsRequest.ProtoReflect.Descriptor instead. func (*GetLogsRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{29} + return file_proto_paas_proto_rawDescGZIP(), []int{31} } func (x *GetLogsRequest) GetProject() string { @@ -1989,7 +2109,7 @@ type GetLogsResponse struct { func (x *GetLogsResponse) Reset() { *x = GetLogsResponse{} - mi := &file_proto_paas_proto_msgTypes[30] + mi := &file_proto_paas_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2001,7 +2121,7 @@ func (x *GetLogsResponse) String() string { func (*GetLogsResponse) ProtoMessage() {} func (x *GetLogsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[30] + mi := &file_proto_paas_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2014,7 +2134,7 @@ func (x *GetLogsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLogsResponse.ProtoReflect.Descriptor instead. func (*GetLogsResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{30} + return file_proto_paas_proto_rawDescGZIP(), []int{32} } func (x *GetLogsResponse) GetLogs() string { @@ -2046,7 +2166,7 @@ type LogEntry struct { func (x *LogEntry) Reset() { *x = LogEntry{} - mi := &file_proto_paas_proto_msgTypes[31] + mi := &file_proto_paas_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2058,7 +2178,7 @@ func (x *LogEntry) String() string { func (*LogEntry) ProtoMessage() {} func (x *LogEntry) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[31] + mi := &file_proto_paas_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2071,7 +2191,7 @@ func (x *LogEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use LogEntry.ProtoReflect.Descriptor instead. func (*LogEntry) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{31} + return file_proto_paas_proto_rawDescGZIP(), []int{33} } func (x *LogEntry) GetTimestamp() string { @@ -2114,7 +2234,7 @@ type ScaleServiceRequest struct { func (x *ScaleServiceRequest) Reset() { *x = ScaleServiceRequest{} - mi := &file_proto_paas_proto_msgTypes[32] + mi := &file_proto_paas_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2126,7 +2246,7 @@ func (x *ScaleServiceRequest) String() string { func (*ScaleServiceRequest) ProtoMessage() {} func (x *ScaleServiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[32] + mi := &file_proto_paas_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2139,7 +2259,7 @@ func (x *ScaleServiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ScaleServiceRequest.ProtoReflect.Descriptor instead. func (*ScaleServiceRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{32} + return file_proto_paas_proto_rawDescGZIP(), []int{34} } func (x *ScaleServiceRequest) GetProject() string { @@ -2179,7 +2299,7 @@ type ScaleServiceResponse struct { func (x *ScaleServiceResponse) Reset() { *x = ScaleServiceResponse{} - mi := &file_proto_paas_proto_msgTypes[33] + mi := &file_proto_paas_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2191,7 +2311,7 @@ func (x *ScaleServiceResponse) String() string { func (*ScaleServiceResponse) ProtoMessage() {} func (x *ScaleServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[33] + mi := &file_proto_paas_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2204,7 +2324,7 @@ func (x *ScaleServiceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ScaleServiceResponse.ProtoReflect.Descriptor instead. func (*ScaleServiceResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{33} + return file_proto_paas_proto_rawDescGZIP(), []int{35} } func (x *ScaleServiceResponse) GetSuccess() bool { @@ -2226,7 +2346,7 @@ type ResourceLimits struct { func (x *ResourceLimits) Reset() { *x = ResourceLimits{} - mi := &file_proto_paas_proto_msgTypes[34] + mi := &file_proto_paas_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2238,7 +2358,7 @@ func (x *ResourceLimits) String() string { func (*ResourceLimits) ProtoMessage() {} func (x *ResourceLimits) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[34] + mi := &file_proto_paas_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2251,7 +2371,7 @@ func (x *ResourceLimits) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceLimits.ProtoReflect.Descriptor instead. func (*ResourceLimits) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{34} + return file_proto_paas_proto_rawDescGZIP(), []int{36} } func (x *ResourceLimits) GetCpuLimit() float64 { @@ -2294,7 +2414,7 @@ type UpdateResourcesRequest struct { func (x *UpdateResourcesRequest) Reset() { *x = UpdateResourcesRequest{} - mi := &file_proto_paas_proto_msgTypes[35] + mi := &file_proto_paas_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2306,7 +2426,7 @@ func (x *UpdateResourcesRequest) String() string { func (*UpdateResourcesRequest) ProtoMessage() {} func (x *UpdateResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[35] + mi := &file_proto_paas_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2319,7 +2439,7 @@ func (x *UpdateResourcesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateResourcesRequest.ProtoReflect.Descriptor instead. func (*UpdateResourcesRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{35} + return file_proto_paas_proto_rawDescGZIP(), []int{37} } func (x *UpdateResourcesRequest) GetProject() string { @@ -2359,7 +2479,7 @@ type UpdateResourcesResponse struct { func (x *UpdateResourcesResponse) Reset() { *x = UpdateResourcesResponse{} - mi := &file_proto_paas_proto_msgTypes[36] + mi := &file_proto_paas_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2371,7 +2491,7 @@ func (x *UpdateResourcesResponse) String() string { func (*UpdateResourcesResponse) ProtoMessage() {} func (x *UpdateResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[36] + mi := &file_proto_paas_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2384,7 +2504,7 @@ func (x *UpdateResourcesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateResourcesResponse.ProtoReflect.Descriptor instead. func (*UpdateResourcesResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{36} + return file_proto_paas_proto_rawDescGZIP(), []int{38} } func (x *UpdateResourcesResponse) GetSuccess() bool { @@ -2408,7 +2528,7 @@ type UpdateDeployRequest struct { func (x *UpdateDeployRequest) Reset() { *x = UpdateDeployRequest{} - mi := &file_proto_paas_proto_msgTypes[37] + mi := &file_proto_paas_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2420,7 +2540,7 @@ func (x *UpdateDeployRequest) String() string { func (*UpdateDeployRequest) ProtoMessage() {} func (x *UpdateDeployRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[37] + mi := &file_proto_paas_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2433,7 +2553,7 @@ func (x *UpdateDeployRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateDeployRequest.ProtoReflect.Descriptor instead. func (*UpdateDeployRequest) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{37} + return file_proto_paas_proto_rawDescGZIP(), []int{39} } func (x *UpdateDeployRequest) GetProject() string { @@ -2487,7 +2607,7 @@ type UpdateDeployResponse struct { func (x *UpdateDeployResponse) Reset() { *x = UpdateDeployResponse{} - mi := &file_proto_paas_proto_msgTypes[38] + mi := &file_proto_paas_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2499,7 +2619,7 @@ func (x *UpdateDeployResponse) String() string { func (*UpdateDeployResponse) ProtoMessage() {} func (x *UpdateDeployResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_paas_proto_msgTypes[38] + mi := &file_proto_paas_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2512,7 +2632,7 @@ func (x *UpdateDeployResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateDeployResponse.ProtoReflect.Descriptor instead. func (*UpdateDeployResponse) Descriptor() ([]byte, []int) { - return file_proto_paas_proto_rawDescGZIP(), []int{38} + return file_proto_paas_proto_rawDescGZIP(), []int{40} } func (x *UpdateDeployResponse) GetSuccess() bool { @@ -2567,7 +2687,16 @@ const file_proto_paas_proto_rawDesc = "" + "\rDomainMapping\x12'\n" + "\x0fcompose_service\x18\x01 \x01(\tR\x0ecomposeService\x12\x16\n" + "\x06domain\x18\x02 \x01(\tR\x06domain\x12\x12\n" + - "\x04port\x18\x03 \x01(\x05R\x04port\"n\n" + + "\x04port\x18\x03 \x01(\x05R\x04port\"\x9a\x01\n" + + "\x1aUpdateComposeSourceRequest\x12\x18\n" + + "\aproject\x18\x01 \x01(\tR\aproject\x12\x18\n" + + "\aservice\x18\x02 \x01(\tR\aservice\x12'\n" + + "\x0fcompose_content\x18\x03 \x01(\tR\x0ecomposeContent\x12\x1f\n" + + "\vskip_deploy\x18\x04 \x01(\bR\n" + + "skipDeploy\"Q\n" + + "\x1bUpdateComposeSourceResponse\x12\x1a\n" + + "\bdeployed\x18\x01 \x01(\bR\bdeployed\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\"n\n" + "\x15DestroyServiceRequest\x12\x18\n" + "\aproject\x18\x01 \x01(\tR\aproject\x12\x18\n" + "\aservice\x18\x02 \x01(\tR\aservice\x12!\n" + @@ -2718,10 +2847,11 @@ const file_proto_paas_proto_rawDesc = "" + "\rzero_downtime\x18\x05 \x01(\bR\fzeroDowntime\x12\x18\n" + "\acommand\x18\x06 \x01(\tR\acommand\"0\n" + "\x14UpdateDeployResponse\x12\x18\n" + - "\asuccess\x18\x01 \x01(\bR\asuccess2\xfc\b\n" + + "\asuccess\x18\x01 \x01(\bR\asuccess2\xd8\t\n" + "\x04PaaS\x12N\n" + "\x0fDeployContainer\x12\x1c.paas.DeployContainerRequest\x1a\x1d.paas.DeployContainerResponse\x12H\n" + - "\rDeployCompose\x12\x1a.paas.DeployComposeRequest\x1a\x1b.paas.DeployComposeResponse\x12K\n" + + "\rDeployCompose\x12\x1a.paas.DeployComposeRequest\x1a\x1b.paas.DeployComposeResponse\x12Z\n" + + "\x13UpdateComposeSource\x12 .paas.UpdateComposeSourceRequest\x1a!.paas.UpdateComposeSourceResponse\x12K\n" + "\x0eDestroyService\x12\x1b.paas.DestroyServiceRequest\x1a\x1c.paas.DestroyServiceResponse\x12Q\n" + "\x10GetServiceStatus\x12\x1d.paas.GetServiceStatusRequest\x1a\x1e.paas.GetServiceStatusResponse\x12E\n" + "\fListServices\x12\x19.paas.ListServicesRequest\x1a\x1a.paas.ListServicesResponse\x12<\n" + @@ -2749,97 +2879,101 @@ func file_proto_paas_proto_rawDescGZIP() []byte { return file_proto_paas_proto_rawDescData } -var file_proto_paas_proto_msgTypes = make([]protoimpl.MessageInfo, 42) +var file_proto_paas_proto_msgTypes = make([]protoimpl.MessageInfo, 44) var file_proto_paas_proto_goTypes = []any{ - (*DeployContainerRequest)(nil), // 0: paas.DeployContainerRequest - (*DeployContainerResponse)(nil), // 1: paas.DeployContainerResponse - (*DeployComposeRequest)(nil), // 2: paas.DeployComposeRequest - (*ComposeDomain)(nil), // 3: paas.ComposeDomain - (*DeployComposeResponse)(nil), // 4: paas.DeployComposeResponse - (*DomainMapping)(nil), // 5: paas.DomainMapping - (*DestroyServiceRequest)(nil), // 6: paas.DestroyServiceRequest - (*DestroyServiceResponse)(nil), // 7: paas.DestroyServiceResponse - (*GetServiceStatusRequest)(nil), // 8: paas.GetServiceStatusRequest - (*GetServiceStatusResponse)(nil), // 9: paas.GetServiceStatusResponse - (*ContainerStatus)(nil), // 10: paas.ContainerStatus - (*ListServicesRequest)(nil), // 11: paas.ListServicesRequest - (*ListServicesResponse)(nil), // 12: paas.ListServicesResponse - (*ServiceInfo)(nil), // 13: paas.ServiceInfo - (*AddDomainRequest)(nil), // 14: paas.AddDomainRequest - (*AddDomainResponse)(nil), // 15: paas.AddDomainResponse - (*RemoveDomainRequest)(nil), // 16: paas.RemoveDomainRequest - (*RemoveDomainResponse)(nil), // 17: paas.RemoveDomainResponse - (*ListDomainsRequest)(nil), // 18: paas.ListDomainsRequest - (*ListDomainsResponse)(nil), // 19: paas.ListDomainsResponse - (*DomainInfo)(nil), // 20: paas.DomainInfo - (*UpdateEnvRequest)(nil), // 21: paas.UpdateEnvRequest - (*UpdateEnvResponse)(nil), // 22: paas.UpdateEnvResponse - (*RestartServiceRequest)(nil), // 23: paas.RestartServiceRequest - (*RestartServiceResponse)(nil), // 24: paas.RestartServiceResponse - (*StopServiceRequest)(nil), // 25: paas.StopServiceRequest - (*StopServiceResponse)(nil), // 26: paas.StopServiceResponse - (*StartServiceRequest)(nil), // 27: paas.StartServiceRequest - (*StartServiceResponse)(nil), // 28: paas.StartServiceResponse - (*GetLogsRequest)(nil), // 29: paas.GetLogsRequest - (*GetLogsResponse)(nil), // 30: paas.GetLogsResponse - (*LogEntry)(nil), // 31: paas.LogEntry - (*ScaleServiceRequest)(nil), // 32: paas.ScaleServiceRequest - (*ScaleServiceResponse)(nil), // 33: paas.ScaleServiceResponse - (*ResourceLimits)(nil), // 34: paas.ResourceLimits - (*UpdateResourcesRequest)(nil), // 35: paas.UpdateResourcesRequest - (*UpdateResourcesResponse)(nil), // 36: paas.UpdateResourcesResponse - (*UpdateDeployRequest)(nil), // 37: paas.UpdateDeployRequest - (*UpdateDeployResponse)(nil), // 38: paas.UpdateDeployResponse - nil, // 39: paas.DeployContainerRequest.EnvEntry - nil, // 40: paas.DeployComposeRequest.EnvEntry - nil, // 41: paas.UpdateEnvRequest.EnvEntry + (*DeployContainerRequest)(nil), // 0: paas.DeployContainerRequest + (*DeployContainerResponse)(nil), // 1: paas.DeployContainerResponse + (*DeployComposeRequest)(nil), // 2: paas.DeployComposeRequest + (*ComposeDomain)(nil), // 3: paas.ComposeDomain + (*DeployComposeResponse)(nil), // 4: paas.DeployComposeResponse + (*DomainMapping)(nil), // 5: paas.DomainMapping + (*UpdateComposeSourceRequest)(nil), // 6: paas.UpdateComposeSourceRequest + (*UpdateComposeSourceResponse)(nil), // 7: paas.UpdateComposeSourceResponse + (*DestroyServiceRequest)(nil), // 8: paas.DestroyServiceRequest + (*DestroyServiceResponse)(nil), // 9: paas.DestroyServiceResponse + (*GetServiceStatusRequest)(nil), // 10: paas.GetServiceStatusRequest + (*GetServiceStatusResponse)(nil), // 11: paas.GetServiceStatusResponse + (*ContainerStatus)(nil), // 12: paas.ContainerStatus + (*ListServicesRequest)(nil), // 13: paas.ListServicesRequest + (*ListServicesResponse)(nil), // 14: paas.ListServicesResponse + (*ServiceInfo)(nil), // 15: paas.ServiceInfo + (*AddDomainRequest)(nil), // 16: paas.AddDomainRequest + (*AddDomainResponse)(nil), // 17: paas.AddDomainResponse + (*RemoveDomainRequest)(nil), // 18: paas.RemoveDomainRequest + (*RemoveDomainResponse)(nil), // 19: paas.RemoveDomainResponse + (*ListDomainsRequest)(nil), // 20: paas.ListDomainsRequest + (*ListDomainsResponse)(nil), // 21: paas.ListDomainsResponse + (*DomainInfo)(nil), // 22: paas.DomainInfo + (*UpdateEnvRequest)(nil), // 23: paas.UpdateEnvRequest + (*UpdateEnvResponse)(nil), // 24: paas.UpdateEnvResponse + (*RestartServiceRequest)(nil), // 25: paas.RestartServiceRequest + (*RestartServiceResponse)(nil), // 26: paas.RestartServiceResponse + (*StopServiceRequest)(nil), // 27: paas.StopServiceRequest + (*StopServiceResponse)(nil), // 28: paas.StopServiceResponse + (*StartServiceRequest)(nil), // 29: paas.StartServiceRequest + (*StartServiceResponse)(nil), // 30: paas.StartServiceResponse + (*GetLogsRequest)(nil), // 31: paas.GetLogsRequest + (*GetLogsResponse)(nil), // 32: paas.GetLogsResponse + (*LogEntry)(nil), // 33: paas.LogEntry + (*ScaleServiceRequest)(nil), // 34: paas.ScaleServiceRequest + (*ScaleServiceResponse)(nil), // 35: paas.ScaleServiceResponse + (*ResourceLimits)(nil), // 36: paas.ResourceLimits + (*UpdateResourcesRequest)(nil), // 37: paas.UpdateResourcesRequest + (*UpdateResourcesResponse)(nil), // 38: paas.UpdateResourcesResponse + (*UpdateDeployRequest)(nil), // 39: paas.UpdateDeployRequest + (*UpdateDeployResponse)(nil), // 40: paas.UpdateDeployResponse + nil, // 41: paas.DeployContainerRequest.EnvEntry + nil, // 42: paas.DeployComposeRequest.EnvEntry + nil, // 43: paas.UpdateEnvRequest.EnvEntry } var file_proto_paas_proto_depIdxs = []int32{ - 39, // 0: paas.DeployContainerRequest.env:type_name -> paas.DeployContainerRequest.EnvEntry - 34, // 1: paas.DeployContainerRequest.resources:type_name -> paas.ResourceLimits - 40, // 2: paas.DeployComposeRequest.env:type_name -> paas.DeployComposeRequest.EnvEntry + 41, // 0: paas.DeployContainerRequest.env:type_name -> paas.DeployContainerRequest.EnvEntry + 36, // 1: paas.DeployContainerRequest.resources:type_name -> paas.ResourceLimits + 42, // 2: paas.DeployComposeRequest.env:type_name -> paas.DeployComposeRequest.EnvEntry 3, // 3: paas.DeployComposeRequest.domains:type_name -> paas.ComposeDomain 5, // 4: paas.DeployComposeResponse.domains:type_name -> paas.DomainMapping - 10, // 5: paas.GetServiceStatusResponse.containers:type_name -> paas.ContainerStatus - 13, // 6: paas.ListServicesResponse.services:type_name -> paas.ServiceInfo - 20, // 7: paas.ListDomainsResponse.domains:type_name -> paas.DomainInfo - 41, // 8: paas.UpdateEnvRequest.env:type_name -> paas.UpdateEnvRequest.EnvEntry - 31, // 9: paas.GetLogsResponse.entries:type_name -> paas.LogEntry - 34, // 10: paas.UpdateResourcesRequest.resources:type_name -> paas.ResourceLimits + 12, // 5: paas.GetServiceStatusResponse.containers:type_name -> paas.ContainerStatus + 15, // 6: paas.ListServicesResponse.services:type_name -> paas.ServiceInfo + 22, // 7: paas.ListDomainsResponse.domains:type_name -> paas.DomainInfo + 43, // 8: paas.UpdateEnvRequest.env:type_name -> paas.UpdateEnvRequest.EnvEntry + 33, // 9: paas.GetLogsResponse.entries:type_name -> paas.LogEntry + 36, // 10: paas.UpdateResourcesRequest.resources:type_name -> paas.ResourceLimits 0, // 11: paas.PaaS.DeployContainer:input_type -> paas.DeployContainerRequest 2, // 12: paas.PaaS.DeployCompose:input_type -> paas.DeployComposeRequest - 6, // 13: paas.PaaS.DestroyService:input_type -> paas.DestroyServiceRequest - 8, // 14: paas.PaaS.GetServiceStatus:input_type -> paas.GetServiceStatusRequest - 11, // 15: paas.PaaS.ListServices:input_type -> paas.ListServicesRequest - 14, // 16: paas.PaaS.AddDomain:input_type -> paas.AddDomainRequest - 16, // 17: paas.PaaS.RemoveDomain:input_type -> paas.RemoveDomainRequest - 18, // 18: paas.PaaS.ListDomains:input_type -> paas.ListDomainsRequest - 21, // 19: paas.PaaS.UpdateEnv:input_type -> paas.UpdateEnvRequest - 23, // 20: paas.PaaS.RestartService:input_type -> paas.RestartServiceRequest - 25, // 21: paas.PaaS.StopService:input_type -> paas.StopServiceRequest - 27, // 22: paas.PaaS.StartService:input_type -> paas.StartServiceRequest - 29, // 23: paas.PaaS.GetLogs:input_type -> paas.GetLogsRequest - 32, // 24: paas.PaaS.ScaleService:input_type -> paas.ScaleServiceRequest - 35, // 25: paas.PaaS.UpdateResources:input_type -> paas.UpdateResourcesRequest - 37, // 26: paas.PaaS.UpdateDeploy:input_type -> paas.UpdateDeployRequest - 1, // 27: paas.PaaS.DeployContainer:output_type -> paas.DeployContainerResponse - 4, // 28: paas.PaaS.DeployCompose:output_type -> paas.DeployComposeResponse - 7, // 29: paas.PaaS.DestroyService:output_type -> paas.DestroyServiceResponse - 9, // 30: paas.PaaS.GetServiceStatus:output_type -> paas.GetServiceStatusResponse - 12, // 31: paas.PaaS.ListServices:output_type -> paas.ListServicesResponse - 15, // 32: paas.PaaS.AddDomain:output_type -> paas.AddDomainResponse - 17, // 33: paas.PaaS.RemoveDomain:output_type -> paas.RemoveDomainResponse - 19, // 34: paas.PaaS.ListDomains:output_type -> paas.ListDomainsResponse - 22, // 35: paas.PaaS.UpdateEnv:output_type -> paas.UpdateEnvResponse - 24, // 36: paas.PaaS.RestartService:output_type -> paas.RestartServiceResponse - 26, // 37: paas.PaaS.StopService:output_type -> paas.StopServiceResponse - 28, // 38: paas.PaaS.StartService:output_type -> paas.StartServiceResponse - 30, // 39: paas.PaaS.GetLogs:output_type -> paas.GetLogsResponse - 33, // 40: paas.PaaS.ScaleService:output_type -> paas.ScaleServiceResponse - 36, // 41: paas.PaaS.UpdateResources:output_type -> paas.UpdateResourcesResponse - 38, // 42: paas.PaaS.UpdateDeploy:output_type -> paas.UpdateDeployResponse - 27, // [27:43] is the sub-list for method output_type - 11, // [11:27] is the sub-list for method input_type + 6, // 13: paas.PaaS.UpdateComposeSource:input_type -> paas.UpdateComposeSourceRequest + 8, // 14: paas.PaaS.DestroyService:input_type -> paas.DestroyServiceRequest + 10, // 15: paas.PaaS.GetServiceStatus:input_type -> paas.GetServiceStatusRequest + 13, // 16: paas.PaaS.ListServices:input_type -> paas.ListServicesRequest + 16, // 17: paas.PaaS.AddDomain:input_type -> paas.AddDomainRequest + 18, // 18: paas.PaaS.RemoveDomain:input_type -> paas.RemoveDomainRequest + 20, // 19: paas.PaaS.ListDomains:input_type -> paas.ListDomainsRequest + 23, // 20: paas.PaaS.UpdateEnv:input_type -> paas.UpdateEnvRequest + 25, // 21: paas.PaaS.RestartService:input_type -> paas.RestartServiceRequest + 27, // 22: paas.PaaS.StopService:input_type -> paas.StopServiceRequest + 29, // 23: paas.PaaS.StartService:input_type -> paas.StartServiceRequest + 31, // 24: paas.PaaS.GetLogs:input_type -> paas.GetLogsRequest + 34, // 25: paas.PaaS.ScaleService:input_type -> paas.ScaleServiceRequest + 37, // 26: paas.PaaS.UpdateResources:input_type -> paas.UpdateResourcesRequest + 39, // 27: paas.PaaS.UpdateDeploy:input_type -> paas.UpdateDeployRequest + 1, // 28: paas.PaaS.DeployContainer:output_type -> paas.DeployContainerResponse + 4, // 29: paas.PaaS.DeployCompose:output_type -> paas.DeployComposeResponse + 7, // 30: paas.PaaS.UpdateComposeSource:output_type -> paas.UpdateComposeSourceResponse + 9, // 31: paas.PaaS.DestroyService:output_type -> paas.DestroyServiceResponse + 11, // 32: paas.PaaS.GetServiceStatus:output_type -> paas.GetServiceStatusResponse + 14, // 33: paas.PaaS.ListServices:output_type -> paas.ListServicesResponse + 17, // 34: paas.PaaS.AddDomain:output_type -> paas.AddDomainResponse + 19, // 35: paas.PaaS.RemoveDomain:output_type -> paas.RemoveDomainResponse + 21, // 36: paas.PaaS.ListDomains:output_type -> paas.ListDomainsResponse + 24, // 37: paas.PaaS.UpdateEnv:output_type -> paas.UpdateEnvResponse + 26, // 38: paas.PaaS.RestartService:output_type -> paas.RestartServiceResponse + 28, // 39: paas.PaaS.StopService:output_type -> paas.StopServiceResponse + 30, // 40: paas.PaaS.StartService:output_type -> paas.StartServiceResponse + 32, // 41: paas.PaaS.GetLogs:output_type -> paas.GetLogsResponse + 35, // 42: paas.PaaS.ScaleService:output_type -> paas.ScaleServiceResponse + 38, // 43: paas.PaaS.UpdateResources:output_type -> paas.UpdateResourcesResponse + 40, // 44: paas.PaaS.UpdateDeploy:output_type -> paas.UpdateDeployResponse + 28, // [28:45] is the sub-list for method output_type + 11, // [11:28] is the sub-list for method input_type 11, // [11:11] is the sub-list for extension type_name 11, // [11:11] is the sub-list for extension extendee 0, // [0:11] is the sub-list for field type_name @@ -2856,7 +2990,7 @@ func file_proto_paas_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_paas_proto_rawDesc), len(file_proto_paas_proto_rawDesc)), NumEnums: 0, - NumMessages: 42, + NumMessages: 44, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/paas.proto b/proto/paas.proto index 5b34788..fa11984 100644 --- a/proto/paas.proto +++ b/proto/paas.proto @@ -12,6 +12,9 @@ service PaaS { // Deploy a full stack from docker-compose content rpc DeployCompose(DeployComposeRequest) returns (DeployComposeResponse); + // Replace the compose content of an existing compose service + rpc UpdateComposeSource(UpdateComposeSourceRequest) returns (UpdateComposeSourceResponse); + // Destroy a deployed service rpc DestroyService(DestroyServiceRequest) returns (DestroyServiceResponse); @@ -103,6 +106,20 @@ message DomainMapping { int32 port = 3; } +// --- Update Compose Source --- + +message UpdateComposeSourceRequest { + string project = 1; + string service = 2; + string compose_content = 3; // full replacement docker-compose.yml content + bool skip_deploy = 4; // store the new content without redeploying +} + +message UpdateComposeSourceResponse { + bool deployed = 1; // false when skip_deploy was set + string status = 2; +} + // --- Destroy --- message DestroyServiceRequest { diff --git a/proto/paas_grpc.pb.go b/proto/paas_grpc.pb.go index caf92cf..345177c 100644 --- a/proto/paas_grpc.pb.go +++ b/proto/paas_grpc.pb.go @@ -19,22 +19,23 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - PaaS_DeployContainer_FullMethodName = "/paas.PaaS/DeployContainer" - PaaS_DeployCompose_FullMethodName = "/paas.PaaS/DeployCompose" - PaaS_DestroyService_FullMethodName = "/paas.PaaS/DestroyService" - PaaS_GetServiceStatus_FullMethodName = "/paas.PaaS/GetServiceStatus" - PaaS_ListServices_FullMethodName = "/paas.PaaS/ListServices" - PaaS_AddDomain_FullMethodName = "/paas.PaaS/AddDomain" - PaaS_RemoveDomain_FullMethodName = "/paas.PaaS/RemoveDomain" - PaaS_ListDomains_FullMethodName = "/paas.PaaS/ListDomains" - PaaS_UpdateEnv_FullMethodName = "/paas.PaaS/UpdateEnv" - PaaS_RestartService_FullMethodName = "/paas.PaaS/RestartService" - PaaS_StopService_FullMethodName = "/paas.PaaS/StopService" - PaaS_StartService_FullMethodName = "/paas.PaaS/StartService" - PaaS_GetLogs_FullMethodName = "/paas.PaaS/GetLogs" - PaaS_ScaleService_FullMethodName = "/paas.PaaS/ScaleService" - PaaS_UpdateResources_FullMethodName = "/paas.PaaS/UpdateResources" - PaaS_UpdateDeploy_FullMethodName = "/paas.PaaS/UpdateDeploy" + PaaS_DeployContainer_FullMethodName = "/paas.PaaS/DeployContainer" + PaaS_DeployCompose_FullMethodName = "/paas.PaaS/DeployCompose" + PaaS_UpdateComposeSource_FullMethodName = "/paas.PaaS/UpdateComposeSource" + PaaS_DestroyService_FullMethodName = "/paas.PaaS/DestroyService" + PaaS_GetServiceStatus_FullMethodName = "/paas.PaaS/GetServiceStatus" + PaaS_ListServices_FullMethodName = "/paas.PaaS/ListServices" + PaaS_AddDomain_FullMethodName = "/paas.PaaS/AddDomain" + PaaS_RemoveDomain_FullMethodName = "/paas.PaaS/RemoveDomain" + PaaS_ListDomains_FullMethodName = "/paas.PaaS/ListDomains" + PaaS_UpdateEnv_FullMethodName = "/paas.PaaS/UpdateEnv" + PaaS_RestartService_FullMethodName = "/paas.PaaS/RestartService" + PaaS_StopService_FullMethodName = "/paas.PaaS/StopService" + PaaS_StartService_FullMethodName = "/paas.PaaS/StartService" + PaaS_GetLogs_FullMethodName = "/paas.PaaS/GetLogs" + PaaS_ScaleService_FullMethodName = "/paas.PaaS/ScaleService" + PaaS_UpdateResources_FullMethodName = "/paas.PaaS/UpdateResources" + PaaS_UpdateDeploy_FullMethodName = "/paas.PaaS/UpdateDeploy" ) // PaaSClient is the client API for PaaS service. @@ -47,6 +48,8 @@ type PaaSClient interface { DeployContainer(ctx context.Context, in *DeployContainerRequest, opts ...grpc.CallOption) (*DeployContainerResponse, error) // Deploy a full stack from docker-compose content DeployCompose(ctx context.Context, in *DeployComposeRequest, opts ...grpc.CallOption) (*DeployComposeResponse, error) + // Replace the compose content of an existing compose service + UpdateComposeSource(ctx context.Context, in *UpdateComposeSourceRequest, opts ...grpc.CallOption) (*UpdateComposeSourceResponse, error) // Destroy a deployed service DestroyService(ctx context.Context, in *DestroyServiceRequest, opts ...grpc.CallOption) (*DestroyServiceResponse, error) // Get service status and info @@ -105,6 +108,16 @@ func (c *paaSClient) DeployCompose(ctx context.Context, in *DeployComposeRequest return out, nil } +func (c *paaSClient) UpdateComposeSource(ctx context.Context, in *UpdateComposeSourceRequest, opts ...grpc.CallOption) (*UpdateComposeSourceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpdateComposeSourceResponse) + err := c.cc.Invoke(ctx, PaaS_UpdateComposeSource_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *paaSClient) DestroyService(ctx context.Context, in *DestroyServiceRequest, opts ...grpc.CallOption) (*DestroyServiceResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(DestroyServiceResponse) @@ -255,6 +268,8 @@ type PaaSServer interface { DeployContainer(context.Context, *DeployContainerRequest) (*DeployContainerResponse, error) // Deploy a full stack from docker-compose content DeployCompose(context.Context, *DeployComposeRequest) (*DeployComposeResponse, error) + // Replace the compose content of an existing compose service + UpdateComposeSource(context.Context, *UpdateComposeSourceRequest) (*UpdateComposeSourceResponse, error) // Destroy a deployed service DestroyService(context.Context, *DestroyServiceRequest) (*DestroyServiceResponse, error) // Get service status and info @@ -299,6 +314,9 @@ func (UnimplementedPaaSServer) DeployContainer(context.Context, *DeployContainer func (UnimplementedPaaSServer) DeployCompose(context.Context, *DeployComposeRequest) (*DeployComposeResponse, error) { return nil, status.Error(codes.Unimplemented, "method DeployCompose not implemented") } +func (UnimplementedPaaSServer) UpdateComposeSource(context.Context, *UpdateComposeSourceRequest) (*UpdateComposeSourceResponse, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateComposeSource not implemented") +} func (UnimplementedPaaSServer) DestroyService(context.Context, *DestroyServiceRequest) (*DestroyServiceResponse, error) { return nil, status.Error(codes.Unimplemented, "method DestroyService not implemented") } @@ -398,6 +416,24 @@ func _PaaS_DeployCompose_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _PaaS_UpdateComposeSource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateComposeSourceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PaaSServer).UpdateComposeSource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PaaS_UpdateComposeSource_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PaaSServer).UpdateComposeSource(ctx, req.(*UpdateComposeSourceRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _PaaS_DestroyService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(DestroyServiceRequest) if err := dec(in); err != nil { @@ -665,6 +701,10 @@ var PaaS_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeployCompose", Handler: _PaaS_DeployCompose_Handler, }, + { + MethodName: "UpdateComposeSource", + Handler: _PaaS_UpdateComposeSource_Handler, + }, { MethodName: "DestroyService", Handler: _PaaS_DestroyService_Handler,