diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7054f12..790e690 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,7 @@ jobs: tags: ${{ steps.create_tag.outputs.tags }} platforms: linux/amd64,linux/arm64 build-args: | - ORKA_VERSION=3.2.0 + ORKA_VERSION=4.0.0 push: true provenance: false env: diff --git a/Dockerfile b/Dockerfile index 356b57f..968b987 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,8 @@ FROM golang:1.25.3 as builder WORKDIR /workspace -ARG ORKA_VERSION=3.1.0 +ARG ORKA_VERSION=4.0.0 +ARG TARGETARCH # Make it runnable on a distroless image/without libc ENV CGO_ENABLED=0 @@ -11,10 +12,15 @@ COPY go.mod go.sum ./ RUN go mod download +# Orka 4.0 renamed the CLI from orka3 to orka and moved its artifacts to the orka/ path. +# Download the build for the target architecture and install it as orka. RUN set -eux \ + && major="${ORKA_VERSION%%.*}" \ + && if [ "$major" -ge 4 ]; then name=orka; else name=orka3; fi \ && curl --location --fail --remote-name \ - https://cli-builds-public.s3.eu-west-1.amazonaws.com/official/${ORKA_VERSION}/orka3/linux/amd64/orka3.tar.gz \ - && tar -xzf orka3.tar.gz -C /usr/local/bin + "https://cli-builds-public.s3.eu-west-1.amazonaws.com/official/${ORKA_VERSION}/${name}/linux/${TARGETARCH:-amd64}/${name}.tar.gz" \ + && tar -xzf "${name}.tar.gz" -C /usr/local/bin \ + && if [ "$name" != orka ]; then mv "/usr/local/bin/${name}" /usr/local/bin/orka; fi COPY . . @@ -25,7 +31,9 @@ FROM alpine:latest WORKDIR / COPY --from=builder /workspace/bin/app /app -COPY --from=builder /usr/local/bin/orka3 /usr/local/bin/orka3 +COPY --from=builder /usr/local/bin/orka /usr/local/bin/orka +# Keep orka3 working for custom scripts written for Orka 3.x. +RUN ln -s orka /usr/local/bin/orka3 RUN addgroup -S appgroup && adduser -S orka -G appgroup diff --git a/README.md b/README.md index 67d885b..0ceb3d8 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ The Orka GitHub runner requires the following environment variabales to be confi * `GITHUB_RUNNER_VERSION`: (Optional) Pins the GitHub Actions runner version deployed to each VM, for example `2.336.0`. Must not include a leading `v`. If not provided, the latest release is looked up from github.com at startup, which requires outbound access to `api.github.com`. * `ORKA_URL`: The URL of the Orka server. * `ORKA_NAMESPACE`: (Optional) The Orka namespace used when deploying VMs. Defaults to `orka-default`. -* `ORKA_TOKEN`: The authentication token for accessing the Orka API. A token can be generated by an admin user with the command `orka3 sa token `. -* `ORKA_VM_CONFIG`: The name of the VM config that will be used when deploying Orka virtual machines. A config can be created with the command `orka3 vmc create --image `. +* `ORKA_TOKEN`: The authentication token for accessing the Orka API. A token can be generated by an admin user with the command `orka sa token `. +* `ORKA_VM_CONFIG`: The name of the VM config that will be used when deploying Orka virtual machines. A config can be created with the command `orka vmc create --image `. * `ORKA_VM_USERNAME`: Specifies the username for the deployed VMs. If no value is provided, it defaults to admin. * `ORKA_VM_PASSWORD`: Specifies the password for the deployed VMs. If no value is provided, it defaults to admin. * `ORKA_VM_METADATA`: Specifies custom VM metadata passed to the VM. Must be formatted as key=value comma separated pairs. diff --git a/examples/.env b/examples/.env index 6749168..ff86b41 100644 --- a/examples/.env +++ b/examples/.env @@ -61,12 +61,12 @@ ORKA_URL="http://10.221.188.20" # ORKA_NAMESPACE="orka-default" # [Required] ORKA_TOKEN should be set to a valid JWT service account token for accessing the Orka service. -# The token can be generated by an admin user using the command 'orka3 sa token '. +# The token can be generated by an admin user using the command 'orka sa token '. ORKA_TOKEN="" # [Required] ORKA_VM_CONFIG specifies the name of the VM configuration to be used. # The config defines various aspects of the virtual machine's setup, such as CPU, memory, and others. -# The config can be created using the command 'orka3 vmc create --image '. +# The config can be created using the command 'orka vmc create --image '. ORKA_VM_CONFIG="my-orka-runner" # [Optional] ORKA_VM_USERNAME and ORKA_VM_PASSWORD specify the credentials used to connect to the diff --git a/pkg/orka/client.go b/pkg/orka/client.go index 0a9b764..a74cc06 100644 --- a/pkg/orka/client.go +++ b/pkg/orka/client.go @@ -12,6 +12,10 @@ import ( "github.com/macstadium/orka-github-actions-integration/pkg/exec" ) +// cliBinary is the Orka CLI executable. Orka 4.0 renamed it from orka3 to orka. +// The container image installs it as orka, with an orka3 symlink. +const cliBinary = "orka" + type OrkaService interface { DeployVM(ctx context.Context, namePrefix, vmConfig string) (*OrkaVMDeployResponseModel, error) DeleteVM(ctx context.Context, name string) error @@ -28,7 +32,7 @@ func (client *OrkaClient) DeployVM(ctx context.Context, namePrefix, vmConfig str args = append(args, "--metadata", client.envData.OrkaVMMetadata) } - res, err := exec.ExecJSONCommand[[]*OrkaVMDeployResponseModel]("orka3", args) + res, err := exec.ExecJSONCommand[[]*OrkaVMDeployResponseModel](cliBinary, args) if err != nil { return nil, err } @@ -37,7 +41,7 @@ func (client *OrkaClient) DeployVM(ctx context.Context, namePrefix, vmConfig str } func (client *OrkaClient) ListVMs(ctx context.Context, namePrefix string) ([]*OrkaVMInfo, error) { - res, err := exec.ExecJSONCommand[[]*OrkaVMInfo]("orka3", []string{"vm", "list", "--namespace", client.envData.OrkaNamespace, "-o", "json"}) + res, err := exec.ExecJSONCommand[[]*OrkaVMInfo](cliBinary, []string{"vm", "list", "--namespace", client.envData.OrkaNamespace, "-o", "json"}) if err != nil { return nil, err } @@ -52,7 +56,7 @@ func (client *OrkaClient) ListVMs(ctx context.Context, namePrefix string) ([]*Or } func (client *OrkaClient) DeleteVM(ctx context.Context, name string) error { - out, err := exec.ExecStringCommand("orka3", []string{"vm", "delete", name, "--namespace", client.envData.OrkaNamespace}) + out, err := exec.ExecStringCommand(cliBinary, []string{"vm", "delete", name, "--namespace", client.envData.OrkaNamespace}) if out == fmt.Sprintf("Successfully deleted vm %s", name) { return nil } @@ -62,7 +66,7 @@ func (client *OrkaClient) DeleteVM(ctx context.Context, name string) error { func NewOrkaClient(envData *env.Data, ctx context.Context) (*OrkaClient, error) { // This request is designed to fail quickly if there is no connectivity to the cluster. - // The orka3 user set-token operation may take up to ~1 minute to fail, which is excessive. + // The orka user set-token operation may take up to ~1 minute to fail, which is excessive. client := &http.Client{ Transport: &OrkaTransport{ Token: envData.OrkaToken, @@ -74,19 +78,19 @@ func NewOrkaClient(envData *env.Data, ctx context.Context) (*OrkaClient, error) return nil, fmt.Errorf("failed to connect to the Orka cluster: %s", err.Error()) } - _, err = exec.ExecStringCommand("orka3", []string{"config", "set", "--api-url", envData.OrkaURL}) + _, err = exec.ExecStringCommand(cliBinary, []string{"config", "set", "--api-url", envData.OrkaURL}) if err != nil { return nil, err } - _, err = exec.ExecStringCommand("orka3", []string{"user", "set-token", envData.OrkaToken}) + _, err = exec.ExecStringCommand(cliBinary, []string{"user", "set-token", envData.OrkaToken}) if err != nil { return nil, err } // The purpose of this call is to check the permissions of the provided token. // If the command fails with an "Unauthorized" error, it indicates that the provided token is not valid. - _, err = exec.ExecStringCommand("orka3", []string{"node", "list", "--namespace", envData.OrkaNamespace}) + _, err = exec.ExecStringCommand(cliBinary, []string{"node", "list", "--namespace", envData.OrkaNamespace}) if err != nil { if strings.Contains(err.Error(), "Unauthorized") { return nil, fmt.Errorf("the provided token is not valid. Please provide a valid token")