Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/e2e-1.32.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ jobs:
- name: Run E2E Tests
run: |
export KUBECONFIG=/home/runner/.kube/config
hack/run-agents-e2e-test.sh --print-info --skip 'Sandbox Upgrade Lifecycle|SandboxUpdateOps E2E'
hack/run-agents-e2e-test.sh --print-info --skip 'Sandbox Upgrade Lifecycle|SandboxUpdateOps E2E|okactl CLI'

61 changes: 61 additions & 0 deletions .github/workflows/e2e-okactl.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: E2E-okactl

on:
push:
branches:
- master
- release-*
pull_request: {}
workflow_dispatch: {}

# Declare default permissions as read only.
permissions: read-all

env:
# Common versions
GO_VERSION: '1.23'
KIND_VERSION: 'v0.22.0'
KIND_IMAGE: 'kindest/node:v1.32.0'
KIND_CLUSTER_NAME: 'ci-testing'

jobs:
okactl:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
- name: Setup Go
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Setup Kind Cluster
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0
with:
node_image: ${{ env.KIND_IMAGE }}
cluster_name: ${{ env.KIND_CLUSTER_NAME }}
config: ./test/kind-conf.yaml
version: ${{ env.KIND_VERSION }}
- name: Build controller image
run: |
export IMAGE="agent-sandbox-controller:latest"
docker build -f dockerfiles/agent-sandbox-controller.Dockerfile --pull --no-cache . -t $IMAGE
kind load docker-image --name=${KIND_CLUSTER_NAME} $IMAGE || { echo >&2 "kind not installed or error loading image: $IMAGE"; exit 1; }
- name: Install Kruise Agents
run: |
CONTROLLER_IMG=agent-sandbox-controller:latest make deploy-agent-sandbox-controller
bash hack/wait-agent-sandbox-controller.sh
- name: Install OpenKruise CRDs
run: |
# Install the ContainerRecreateRequest CRD so okactl restart can be tested
kubectl apply -f https://raw.githubusercontent.com/openkruise/kruise/master/config/crd/bases/apps.kruise.io_containerrecreaterequests.yaml || true
- name: Build okactl
run: |
make build-okactl
echo "$(pwd)/bin" >> $GITHUB_PATH
- name: Run okactl E2E Tests
run: |
export KUBECONFIG=/home/runner/.kube/config
export OKACTL_BIN=$(pwd)/bin/okactl
make ginkgo
./bin/ginkgo -timeout 10m -v --fail-fast --focus='okactl CLI' test/e2e
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
bin/*
Dockerfile.cross

# Pre-built okactl binary (distributed via GitHub Releases)
okactl

# Test binary, built with `go test -c`
*.test

Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ vet: ## Run go vet against code.
build: generate fmt vet manifests ## Build manager binary.
go build -o bin/agent-sandbox-controller cmd/agent-sandbox-controller/main.go

.PHONY: build-okactl
build-okactl: ## Build okactl CLI binary.
go build -o bin/okactl ./cmd/okactl


# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
Expand Down
115 changes: 115 additions & 0 deletions cmd/okactl/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
Copyright 2026.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description is severely outdated and does not match the actual implementation.

The PR description mentions:

  • Binary name: agent-cli → Actual: okactl
  • Path: cmd/agent-cli/ → Actual: cmd/okactl/
  • New CRD: SandboxContainerRestart (scr) → Actual: uses OpenKruise ContainerRecreateRequest (CRR), no new CRD
  • New controller: pkg/controller/sandboxcontainerrestart/ → Actual: no new controller
  • 3 commands → Actual: 5 commands (scale, set image, restart, create suo, status)
  • Included 47MB binary to be removed → Actual: binary already removed, .gitignore added

Please update the PR description to accurately reflect the current implementation.


import (
"fmt"
"os"
"strings"

"github.com/spf13/cobra"

"github.com/openkruise/agents/pkg/cli"
)

// usageTemplate is a custom cobra usage template that displays subcommand aliases.
// It is based on cobra's defaultUsageTemplate with alias support added to the
// Available Commands sections.
const usageTemplate = `Usage:{{if .Runnable}}
{{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
{{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}

Aliases:
{{.NameAndAliases}}{{end}}{{if .HasExample}}

Examples:
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}}

Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
{{rpad .Name .NamePadding }}{{if .Aliases}} ({{join .Aliases ", "}}){{end}} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}

{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}}
{{rpad .Name .NamePadding }}{{if .Aliases}} ({{join .Aliases ", "}}){{end}} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}

Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}}
{{rpad .Name .NamePadding }}{{if .Aliases}} ({{join .Aliases ", "}}){{end}} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}

Flags:
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}

Global Flags:
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}

Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}

Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`

func main() {
const (
groupResource = "resource"
groupOther = "other"
)

globalOpts := cli.NewGlobalOptions()

root := &cobra.Command{
Use: "okactl",
Short: "okactl controls the OpenKruise Agents sandbox cluster",
Long: `okactl controls the OpenKruise Agents sandbox cluster.

Find more information at: https://github.com/openkruise/agents`,
SilenceUsage: true,
SilenceErrors: true,
}

globalOpts.AddFlags(root.PersistentFlags())

root.AddGroup(&cobra.Group{ID: groupResource, Title: "Resource Commands:"})
root.AddGroup(&cobra.Group{ID: groupOther, Title: "Other Commands:"})

// Register custom template functions and customize usage template to show
// subcommand aliases in the Available Commands list.
cobra.AddTemplateFunc("join", strings.Join)
root.SetUsageTemplate(usageTemplate)

scaleCmd := cli.NewScaleCommand(globalOpts)
scaleCmd.GroupID = groupResource
setCmd := cli.NewSetCommand(globalOpts)
setCmd.GroupID = groupResource
restartCmd := cli.NewRestartCommand(globalOpts)
restartCmd.GroupID = groupResource
createCmd := cli.NewCreateCommand(globalOpts)
createCmd.GroupID = groupResource
statusCmd := cli.NewStatusCommand(globalOpts)
statusCmd.GroupID = groupResource

root.AddCommand(scaleCmd, setCmd, restartCmd, createCmd, statusCmd)

// Assign group ID to auto-generated commands (completion, help)
for _, cmd := range root.Commands() {
if cmd.GroupID == "" {
cmd.GroupID = groupOther
}
}

if err := root.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
Loading
Loading