diff --git a/cmd/unikraft/testdata/TestGolden/auth/help b/cmd/unikraft/testdata/TestGolden/auth/help index eb290d33..a9067bde 100644 --- a/cmd/unikraft/testdata/TestGolden/auth/help +++ b/cmd/unikraft/testdata/TestGolden/auth/help @@ -120,6 +120,9 @@ stdout: # Inspect a profile by name unikraft profile get default + # Show the currently active profile + unikraft profile list --filter 'active==true' + Fields: name active @@ -166,6 +169,9 @@ stdout: # List all profiles unikraft profile list + # List profiles in JSON format + unikraft profile list -o json + Fields: name active @@ -304,6 +310,9 @@ stdout: # Inspect a metro by name unikraft metro get fra + # Show all metro details including status and quotas + unikraft metro get fra -f +status,+quotas + Fields: name country @@ -368,12 +377,15 @@ stdout: # List all metros unikraft metro list - # List metros with connection status + # List metros with latency and online status unikraft metro list -f +status # List metros with quota usage unikraft metro list -f +quotas + # Output metro list as JSON + unikraft metro list -o json + Fields: name country diff --git a/cmd/unikraft/testdata/TestGolden/build/help b/cmd/unikraft/testdata/TestGolden/build/help index deafbe31..65442cb0 100644 --- a/cmd/unikraft/testdata/TestGolden/build/help +++ b/cmd/unikraft/testdata/TestGolden/build/help @@ -15,12 +15,15 @@ stdout: # Build the project in the current directory unikraft build . - # Build and publish an image from a Kraftfile + # Build and publish an image to a registry unikraft build . --output my-org/my-app:latest # Build with custom build arguments unikraft build ./app --build-arg VERSION=1.2.3 --build-arg COMMIT=abc123 + # Build without using cache + unikraft build . --no-cache + # Build with secret and SSH access unikraft build . --secret id=npm,src=$HOME/.npmrc --ssh default=$SSH_AUTH_SOCK diff --git a/cmd/unikraft/testdata/TestGolden/certificates/help b/cmd/unikraft/testdata/TestGolden/certificates/help index f44a9b2b..8fa4e794 100644 --- a/cmd/unikraft/testdata/TestGolden/certificates/help +++ b/cmd/unikraft/testdata/TestGolden/certificates/help @@ -62,9 +62,18 @@ stdout: Target certificates to get. Examples: - # Get a certificate by name or UUID + # Inspect a certificate by name unikraft certificate get demo-cert + # Inspect a certificate by UUID + unikraft certificate get 12345678-1234-1234-1234-123456789abc + + # Inspect a certificate in a specific metro + unikraft certificate get fra/demo-cert + + # Show certificate details in JSON format + unikraft certificate get demo-cert -o json + Fields: metro name @@ -117,9 +126,12 @@ stdout: Target certificates to list. Examples: - # List all certificates + # List all certificates across metros unikraft certificate list + # List certificates and watch for changes + unikraft certificate list -w + Fields: metro name @@ -232,7 +244,7 @@ stdout: unikraft certificates create [flags] Examples: - # Create a new certificate + # Create a self-signed certificate and upload it openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes \ -subj "/CN=demo.unikraft.dev" \ -keyout cert.key \ @@ -244,6 +256,14 @@ stdout: --pkey cert.key \ --metro fra + # Preview certificate creation without applying + unikraft certificate create \ + --cn example.com. \ + --chain cert.pem \ + --pkey cert.key \ + --metro sfo \ + --dry-run + Fields: metro name @@ -318,9 +338,15 @@ stdout: Target certificates to remove. Examples: - # Delete a certificate by name or UUID + # Delete a certificate by name unikraft certificate delete demo-cert + # Delete a certificate by UUID + unikraft certificate delete 12345678-1234-1234-1234-123456789abc + + # Delete all certificates (with confirmation prompt) + unikraft certificate delete --all + Fields: metro name diff --git a/cmd/unikraft/testdata/TestGolden/config/help b/cmd/unikraft/testdata/TestGolden/config/help index 7220cb0d..e368c4ee 100644 --- a/cmd/unikraft/testdata/TestGolden/config/help +++ b/cmd/unikraft/testdata/TestGolden/config/help @@ -52,6 +52,12 @@ stdout: # Show the current configuration unikraft config get + # Show config from a specific file + unikraft config get /path/to/config.yaml + + # Show a specific field in JSON format + unikraft config get -f profiles -o json + Fields: path profile diff --git a/cmd/unikraft/testdata/TestGolden/help/empty b/cmd/unikraft/testdata/TestGolden/help/empty index f4b5904c..39e9935c 100644 --- a/cmd/unikraft/testdata/TestGolden/help/empty +++ b/cmd/unikraft/testdata/TestGolden/help/empty @@ -56,15 +56,18 @@ stdout: # Login to Unikraft Cloud unikraft login - # List instances across metros - unikraft instances list + # List instances across all metros + unikraft instance list # Build and publish an image from a Kraftfile unikraft build . --output my-org/my-app:latest # Deploy a new instance from an image - unikraft run --metro=sfo --image=nginx:latest --autostart -p 443:8080/http+tls - --scale-to-zero policy=on + unikraft run --metro=fra --image=nginx:latest -p 443:8080/http+tls --scale-to- + zero on + + # Browse resources in an interactive TUI + unikraft tui # Switch to a different profile unikraft profile use my-other-profile diff --git a/cmd/unikraft/testdata/TestGolden/help/help b/cmd/unikraft/testdata/TestGolden/help/help index b65f973c..24a0d96e 100644 --- a/cmd/unikraft/testdata/TestGolden/help/help +++ b/cmd/unikraft/testdata/TestGolden/help/help @@ -56,15 +56,18 @@ stdout: # Login to Unikraft Cloud unikraft login - # List instances across metros - unikraft instances list + # List instances across all metros + unikraft instance list # Build and publish an image from a Kraftfile unikraft build . --output my-org/my-app:latest # Deploy a new instance from an image - unikraft run --metro=sfo --image=nginx:latest --autostart -p 443:8080/http+tls - --scale-to-zero policy=on + unikraft run --metro=fra --image=nginx:latest -p 443:8080/http+tls --scale-to- + zero on + + # Browse resources in an interactive TUI + unikraft tui # Switch to a different profile unikraft profile use my-other-profile diff --git a/cmd/unikraft/testdata/TestGolden/help/invalid/help b/cmd/unikraft/testdata/TestGolden/help/invalid/help index 12204cf3..58b3cefe 100644 --- a/cmd/unikraft/testdata/TestGolden/help/invalid/help +++ b/cmd/unikraft/testdata/TestGolden/help/invalid/help @@ -56,15 +56,18 @@ stdout: # Login to Unikraft Cloud unikraft login - # List instances across metros - unikraft instances list + # List instances across all metros + unikraft instance list # Build and publish an image from a Kraftfile unikraft build . --output my-org/my-app:latest # Deploy a new instance from an image - unikraft run --metro=sfo --image=nginx:latest --autostart -p 443:8080/http+tls - --scale-to-zero policy=on + unikraft run --metro=fra --image=nginx:latest -p 443:8080/http+tls --scale-to- + zero on + + # Browse resources in an interactive TUI + unikraft tui # Switch to a different profile unikraft profile use my-other-profile @@ -153,15 +156,18 @@ stdout: # Login to Unikraft Cloud unikraft login - # List instances across metros - unikraft instances list + # List instances across all metros + unikraft instance list # Build and publish an image from a Kraftfile unikraft build . --output my-org/my-app:latest # Deploy a new instance from an image - unikraft run --metro=sfo --image=nginx:latest --autostart -p 443:8080/http+tls - --scale-to-zero policy=on + unikraft run --metro=fra --image=nginx:latest -p 443:8080/http+tls --scale-to- + zero on + + # Browse resources in an interactive TUI + unikraft tui # Switch to a different profile unikraft profile use my-other-profile diff --git a/cmd/unikraft/testdata/TestGolden/images/help b/cmd/unikraft/testdata/TestGolden/images/help index f29e1de0..99340164 100644 --- a/cmd/unikraft/testdata/TestGolden/images/help +++ b/cmd/unikraft/testdata/TestGolden/images/help @@ -54,6 +54,12 @@ stdout: # Inspect an image by tag unikraft image get nginx:latest + # Show image details in JSON format + unikraft image get nginx:latest -o json + + # Show all image fields including kernel and initrd info + unikraft image get my-app:v1.0 -f +kernel,+initrd + Fields: ref digest @@ -110,6 +116,9 @@ stdout: # Filter images by reference unikraft image list --filter 'ref~="/nginx"' + # List images in table format + unikraft image list -o table + Fields: ref digest @@ -161,16 +170,20 @@ stdout: Destination image reference. Examples: - # Create a copy of an image + # Copy an official image to your namespace unikraft image copy unikraft.io/official/nginx:latest unikraft.io/my-user/my- - nginx + nginx:latest - # Upload a local image to a remote registry + # Upload a local OCI archive to a remote registry unikraft image copy ./my-local-image.tar unikraft.io/my-user/my-image:1.0.0 - # Download an image from a remote registry + # Download an image to a local archive unikraft image copy unikraft.io/official/redis:latest ./my-redis-image.tar + # Tag an image with a new version + unikraft image copy unikraft.io/my-user/my-app:latest unikraft.io/my-user/my- + app:v2.0 + Global flags: -h, --help Show context-sensitive help. diff --git a/cmd/unikraft/testdata/TestGolden/instances/help b/cmd/unikraft/testdata/TestGolden/instances/help index 1f1678e5..be3b489c 100644 --- a/cmd/unikraft/testdata/TestGolden/instances/help +++ b/cmd/unikraft/testdata/TestGolden/instances/help @@ -88,9 +88,21 @@ stdout: Target instances to get. Examples: - # Inspect an instance by name or UUID + # Inspect an instance by name unikraft instance get demo-instance + # Inspect an instance by UUID + unikraft instance get 12345678-1234-1234-1234-123456789abc + + # Inspect an instance in a specific metro + unikraft instance get fra/demo-instance + + # Show instance details in JSON format + unikraft instance get demo-instance -o json + + # Watch instance state changes in real-time + unikraft instance get demo-instance -w + Fields: metro name @@ -153,9 +165,21 @@ stdout: Target instances to list. Examples: - # List instances across metros + # List instances across all metros unikraft instance list + # List only running instances + unikraft instance list --filter 'state=="running"' + + # List instances sorted by creation time (newest first) + unikraft instance list --sort -timestamps.created + + # Watch instances and refresh every 5 seconds + unikraft instance list -w 5s + + # List instances as a table with additional fields + unikraft instance list -f +resources -o table + Fields: metro name @@ -288,14 +312,15 @@ stdout: unikraft instances create [flags] Examples: - # Create a new instance + # Create a new instance with HTTPS port exposed unikraft instance create \ --name demo-instance \ --metro fra \ --image nginx:latest \ --autostart \ - --memory 128 \ - --vcpus 1 + -m 128MiB \ + --vcpus 1 \ + -p 443:8080/http+tls # Create an instance from a template unikraft instance create \ @@ -303,6 +328,32 @@ stdout: --metro fra \ --template my-template + # Create an instance with environment variables and a volume + unikraft instance create \ + --metro sfo \ + --image my-app:latest \ + -e DB_HOST=db.example.com \ + -e DB_PORT=5432 \ + -v data-vol:/data \ + --autostart + + # Create an instance with scale-to-zero enabled + unikraft instance create \ + --metro fra \ + --image my-app:latest \ + --scale-to-zero policy=on,cooldown-time=300 \ + -p 443:8080/http+tls \ + --autostart + + # Preview instance creation without applying + unikraft instance create \ + --metro dal \ + --image nginx:latest \ + --dry-run + + # Save creatable fields to a YAML file for later use + unikraft instance create --save instance.yaml --dry-run + Fields: metro name @@ -425,7 +476,19 @@ stdout: Examples: # Resize instance memory - unikraft instance edit demo-instance --memory 256 + unikraft instance edit demo-instance -m 256MiB + + # Update the image of an instance + unikraft instance edit demo-instance --image my-app:v2.0 + + # Change environment variables + unikraft instance edit demo-instance --set runtime.env.DEBUG=true + + # Enable scale-to-zero on an existing instance + unikraft instance edit demo-instance --scale-to-zero on + + # Preview edits without applying them + unikraft instance edit demo-instance -m 512MiB --dry-run Fields: metro @@ -524,9 +587,18 @@ stdout: Target instances to remove. Examples: - # Delete an instance by name or UUID + # Delete an instance by name unikraft instance delete demo-instance + # Delete an instance by UUID + unikraft instance delete 12345678-1234-1234-1234-123456789abc + + # Delete multiple instances at once + unikraft instance delete instance-1 instance-2 + + # Delete all stopped instances (with confirmation) + unikraft instance delete --filter 'state=="stopped"' + Fields: metro name @@ -647,9 +719,15 @@ stdout: Target instance-templates to get. Examples: - # Inspect an instance template by name or UUID + # Inspect an instance template by name unikraft instance template get demo-template + # Inspect an instance template by UUID + unikraft instance template get 12345678-1234-1234-1234-123456789abc + + # Show template details in JSON format + unikraft instance template get demo-template -o json + Fields: metro name @@ -707,6 +785,9 @@ stdout: # List instance templates across metros unikraft instance template list + # List templates in table format + unikraft instance template list -o table + Fields: metro name @@ -770,6 +851,9 @@ stdout: # Convert a stopped instance into a template unikraft instance template create demo-instance + # Convert multiple instances into templates + unikraft instance template create instance-1 instance-2 + Fields: metro name @@ -833,7 +917,10 @@ stdout: Examples: # Update template tags - unikraft instance template edit demo-template --set tags=env-dev + unikraft instance template edit demo-template --tags env-prod,team-platform + + # Lock a template to prevent deletion + unikraft instance template edit demo-template --delete-lock Fields: metro @@ -911,6 +998,9 @@ stdout: # Delete an instance template unikraft instance template delete demo-template + # Delete all instance templates (with confirmation) + unikraft instance template delete --all + Fields: metro name @@ -973,12 +1063,21 @@ stdout: # Fetch logs from an instance unikraft instance logs my-instance - # Fetch the last 100 lines of logs from an instance + # Fetch the last 100 lines of logs unikraft instance logs my-instance --tail 100 # Follow logs from an instance in real-time unikraft instance logs my-instance --follow + # Fetch logs from a specific metro + unikraft instance logs fra/my-instance + + # Follow logs from multiple instances + unikraft instance logs instance-1 instance-2 --follow + + # Follow logs without instance name prefix + unikraft instance logs my-instance --follow --no-prefix + Flags: --[no-]prefix Prefix log lines with instance name. @@ -1021,6 +1120,12 @@ stdout: # Start an instance unikraft instance start demo-instance + # Start multiple instances at once + unikraft instance start instance-1 instance-2 instance-3 + + # Start an instance in a specific metro + unikraft instance start fra/demo-instance + Flags: -f, --field Specify which fields to include in the output. @@ -1057,15 +1162,18 @@ stdout: Target instances to stop. Examples: - # Stop an instance + # Stop an instance gracefully unikraft instance stop demo-instance - # Stop with a drain timeout + # Stop with a drain timeout to allow in-flight requests to complete unikraft instance stop demo-instance --drain-timeout 30000 - # Force stop an instance + # Force stop an instance immediately unikraft instance stop demo-instance --force + # Stop multiple instances + unikraft instance stop instance-1 instance-2 + Flags: --force Force stop the instance immediately. @@ -1107,12 +1215,15 @@ stdout: Target instances to suspend. Examples: - # Suspend an instance + # Suspend an instance (preserves state for fast resume) unikraft instance suspend demo-instance - # Suspend with a drain timeout + # Suspend with a drain timeout to allow in-flight requests to complete unikraft instance suspend demo-instance --drain-timeout 30000 + # Suspend multiple instances + unikraft instance suspend instance-1 instance-2 + Flags: --drain-timeout Timeout in milliseconds for draining connections before suspending. @@ -1152,12 +1263,15 @@ stdout: Target instances to restart. Examples: - # Restart an instance + # Restart an instance gracefully unikraft instance restart demo-instance - # Force restart an instance + # Force restart an instance (skips graceful shutdown) unikraft instance restart demo-instance --force + # Restart with a drain timeout + unikraft instance restart demo-instance --drain-timeout 10000 + Flags: --force Force stop the instance immediately. diff --git a/cmd/unikraft/testdata/TestGolden/services/help b/cmd/unikraft/testdata/TestGolden/services/help index 2adfb8f4..9bbec2d7 100644 --- a/cmd/unikraft/testdata/TestGolden/services/help +++ b/cmd/unikraft/testdata/TestGolden/services/help @@ -62,9 +62,18 @@ stdout: Target services to get. Examples: - # Inspect a service group by name or UUID + # Inspect a service group by name unikraft service get demo-service + # Inspect a service group by UUID + unikraft service get 12345678-1234-1234-1234-123456789abc + + # Inspect a service group in a specific metro + unikraft service get fra/demo-service + + # Show service details in JSON format + unikraft service get demo-service -o json + Fields: metro name @@ -115,9 +124,12 @@ stdout: Target services to list. Examples: - # List all service groups + # List all service groups across metros unikraft service list + # List services and watch for changes + unikraft service list -w + Fields: metro name @@ -226,12 +238,35 @@ stdout: unikraft services create [flags] Examples: - # Create a new service group + # Create a service group with HTTPS unikraft service create \ --name demo-service \ --metro fra \ --domains demo \ - --services 443:8080/tls+http + --services 443:8080/http+tls + + # Create a service group with HTTPS and HTTP-to-HTTPS redirect + unikraft service create \ + --name web-service \ + --metro fra \ + --domains my-app.example.com \ + --services 443:8080/http+tls \ + --services 80:443/http+redirect + + # Create a service group with rate limits + unikraft service create \ + --name api-service \ + --metro fra \ + --services 443:8080/http+tls \ + --soft-limit 100 \ + --hard-limit 200 + + # Preview service creation without applying + unikraft service create \ + --name test-service \ + --metro fra \ + --services 443:8080/http+tls \ + --dry-run Fields: metro @@ -311,7 +346,16 @@ stdout: Examples: # Add a new service port - unikraft service edit demo-service --services 8443:8080/tls + unikraft service edit demo-service --add services=8443:9090/http+tls + + # Add a domain to a service group + unikraft service edit demo-service --add domains=api.example.com + + # Update rate limits + unikraft service edit demo-service --soft-limit 50 --hard-limit 100 + + # Remove a domain from a service group + unikraft service edit demo-service --del domains=old.example.com Fields: metro @@ -389,9 +433,15 @@ stdout: Target services to remove. Examples: - # Delete a service group by name or UUID + # Delete a service group by name unikraft service delete demo-service + # Delete a service group by UUID + unikraft service delete 12345678-1234-1234-1234-123456789abc + + # Delete all service groups (with confirmation) + unikraft service delete --all + Fields: metro name diff --git a/cmd/unikraft/testdata/TestGolden/volumes/help b/cmd/unikraft/testdata/TestGolden/volumes/help index 130354bf..d5db807f 100644 --- a/cmd/unikraft/testdata/TestGolden/volumes/help +++ b/cmd/unikraft/testdata/TestGolden/volumes/help @@ -72,9 +72,18 @@ stdout: Target volumes to get. Examples: - # Inspect a volume by name or UUID + # Inspect a volume by name unikraft volume get demo-volume + # Inspect a volume by UUID + unikraft volume get 12345678-1234-1234-1234-123456789abc + + # Inspect a volume in a specific metro + unikraft volume get fra/demo-volume + + # Show volume details in JSON format + unikraft volume get demo-volume -o json + Fields: metro name @@ -127,9 +136,15 @@ stdout: Target volumes to list. Examples: - # List all volumes + # List all volumes across metros unikraft volume list + # List volumes and watch for state changes + unikraft volume list -w + + # List volumes with attachment information + unikraft volume list -f +attached-to + Fields: metro name @@ -242,12 +257,26 @@ stdout: unikraft volumes create [flags] Examples: - # Create a new volume + # Create a 10 GiB volume unikraft volume create \ --name demo-volume \ - --size 10 \ + --size 10GiB \ + --metro fra + + # Create a volume with ext4 filesystem + unikraft volume create \ + --name app-data \ + --size 5GiB \ + --filesystem ext4 \ --metro fra + # Preview volume creation without applying + unikraft volume create \ + --name test-vol \ + --size 1GiB \ + --metro fra \ + --dry-run + Fields: metro name @@ -327,6 +356,9 @@ stdout: # Clone a volume with a new name unikraft volume clone demo-volume --name demo-volume-clone + # Clone a volume with tags + unikraft volume clone demo-volume --name backup --tags env=staging + Flags: --set==, --set-file== Key-value pairs to set on the volume. @@ -384,6 +416,9 @@ stdout: # Import a Dockerfile context into a volume unikraft volume import my-volume --source ./Dockerfile + # Force import even if data exceeds volume capacity + unikraft volume import my-volume --source ./large-data --force + Flags: -s, --source= Data source: local directory, CPIO archive, or Dockerfile. @@ -421,7 +456,10 @@ stdout: Examples: # Resize a volume - unikraft volume edit demo-volume --size 20 + unikraft volume edit demo-volume --size 20GiB + + # Change the quota policy + unikraft volume edit demo-volume --quota-policy dynamic Fields: metro @@ -495,9 +533,15 @@ stdout: Target volumes to remove. Examples: - # Delete a volume by name or UUID + # Delete a volume by name unikraft volume delete demo-volume + # Delete a volume by UUID + unikraft volume delete 12345678-1234-1234-1234-123456789abc + + # Delete all volumes (with confirmation) + unikraft volume delete --all + Fields: metro name diff --git a/internal/cmd/build.go b/internal/cmd/build.go index 36b7f374..06a5c419 100644 --- a/internal/cmd/build.go +++ b/internal/cmd/build.go @@ -38,7 +38,7 @@ func (BuildCmd) Examples() []kingkong.Example { }, }, { - Description: "Build and publish an image from a Kraftfile", + Description: "Build and publish an image to a registry", Commands: []string{ "unikraft build . --output my-org/my-app:latest", }, @@ -49,6 +49,12 @@ func (BuildCmd) Examples() []kingkong.Example { "unikraft build ./app --build-arg VERSION=1.2.3 --build-arg COMMIT=abc123", }, }, + { + Description: "Build without using cache", + Commands: []string{ + "unikraft build . --no-cache", + }, + }, { Description: "Build with secret and SSH access", Commands: []string{ diff --git a/internal/cmd/certificates.go b/internal/cmd/certificates.go index 3818b3ac..eb6b2501 100644 --- a/internal/cmd/certificates.go +++ b/internal/cmd/certificates.go @@ -278,30 +278,40 @@ func (Certificate) Examples() map[cmd.CmdType][]kingkong.Example { return map[cmd.CmdType][]kingkong.Example{ cmd.CmdTypeGet: { { - Description: "Get a certificate by name or UUID", + Description: "Inspect a certificate by name", Commands: []string{"unikraft certificate get demo-cert"}, }, + { + Description: "Inspect a certificate by UUID", + Commands: []string{"unikraft certificate get d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Inspect a certificate in a specific metro", + Commands: []string{"unikraft certificate get fra/demo-cert"}, + }, + { + Description: "Show certificate details in JSON format", + Commands: []string{"unikraft certificate get demo-cert -o json"}, + }, }, cmd.CmdTypeList: { { - Description: "List all certificates", + Description: "List all certificates across metros", Commands: []string{"unikraft certificate list"}, }, + { + Description: "List certificates and watch for changes", + Commands: []string{"unikraft certificate list -w"}, + }, }, cmd.CmdTypeCreate: { { - Description: "Create a new certificate", + Description: "Create a self-signed certificate and upload it", Commands: []string{ `openssl req -x509 -newkey rsa:2048 -sha256 -days 365 -nodes \ -subj "/CN=demo.unikraft.dev" \ -keyout cert.key \ -out cert.pem`, - // `unikraft certificate create \ - // --set name=demo-cert \ - // --set cn=demo.unikraft.dev. \ - // --set-file chain=cert.pem \ - // --set-file pkey=cert.key \ - // --set metro=fra`, `unikraft certificate create \ --name demo-cert \ --cn demo.unikraft.dev. \ @@ -310,12 +320,31 @@ func (Certificate) Examples() map[cmd.CmdType][]kingkong.Example { --metro fra`, }, }, + { + Description: "Preview certificate creation without applying", + Commands: []string{ + `unikraft certificate create \ + --cn example.com. \ + --chain cert.pem \ + --pkey cert.key \ + --metro sfo \ + --dry-run`, + }, + }, }, cmd.CmdTypeDelete: { { - Description: "Delete a certificate by name or UUID", + Description: "Delete a certificate by name", Commands: []string{"unikraft certificate delete demo-cert"}, }, + { + Description: "Delete a certificate by UUID", + Commands: []string{"unikraft certificate delete d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Delete all certificates (with confirmation prompt)", + Commands: []string{"unikraft certificate delete --all"}, + }, }, } } diff --git a/internal/cmd/config.go b/internal/cmd/config.go index 15cbb39f..f9172c8e 100644 --- a/internal/cmd/config.go +++ b/internal/cmd/config.go @@ -83,6 +83,14 @@ func (Config) Examples() map[cmd.CmdType][]kingkong.Example { Description: "Show the current configuration", Commands: []string{"unikraft config get"}, }, + { + Description: "Show config from a specific file", + Commands: []string{"unikraft config get /path/to/config.yaml"}, + }, + { + Description: "Show a specific field in JSON format", + Commands: []string{"unikraft config get -f profiles -o json"}, + }, }, } } diff --git a/internal/cmd/images.go b/internal/cmd/images.go index f9c0d4cc..739e3881 100644 --- a/internal/cmd/images.go +++ b/internal/cmd/images.go @@ -224,6 +224,14 @@ func (Image) Examples() map[cmd.CmdType][]kingkong.Example { Description: "Inspect an image by tag", Commands: []string{"unikraft image get nginx:latest"}, }, + { + Description: "Show image details in JSON format", + Commands: []string{"unikraft image get nginx:latest -o json"}, + }, + { + Description: "Show all image fields including kernel and initrd info", + Commands: []string{"unikraft image get my-app:v1.0 -f +kernel,+initrd"}, + }, }, cmd.CmdTypeList: { { @@ -234,6 +242,10 @@ func (Image) Examples() map[cmd.CmdType][]kingkong.Example { Description: "Filter images by reference", Commands: []string{`unikraft image list --filter 'ref~="/nginx"'`}, }, + { + Description: "List images in table format", + Commands: []string{"unikraft image list -o table"}, + }, }, cmd.CmdTypeDelete: { { @@ -648,23 +660,29 @@ type ImagesCopyCmd struct { func (cmd ImagesCopyCmd) Examples() []kingkong.Example { return []kingkong.Example{ { - Description: "Create a copy of an image", + Description: "Copy an official image to your namespace", Commands: []string{ - "unikraft image copy unikraft.io/official/nginx:latest unikraft.io/my-user/my-nginx", + "unikraft image copy unikraft.io/official/nginx:latest unikraft.io/my-user/my-nginx:latest", }, }, { - Description: "Upload a local image to a remote registry", + Description: "Upload a local OCI archive to a remote registry", Commands: []string{ "unikraft image copy ./my-local-image.tar unikraft.io/my-user/my-image:1.0.0", }, }, { - Description: "Download an image from a remote registry", + Description: "Download an image to a local archive", Commands: []string{ "unikraft image copy unikraft.io/official/redis:latest ./my-redis-image.tar", }, }, + { + Description: "Tag an image with a new version", + Commands: []string{ + "unikraft image copy unikraft.io/my-user/my-app:latest unikraft.io/my-user/my-app:v2.0", + }, + }, } } diff --git a/internal/cmd/instance_templates.go b/internal/cmd/instance_templates.go index 1539f097..c5bf581d 100644 --- a/internal/cmd/instance_templates.go +++ b/internal/cmd/instance_templates.go @@ -412,27 +412,49 @@ func (InstanceTemplate) Examples() map[cmd.CmdType][]kingkong.Example { return map[cmd.CmdType][]kingkong.Example{ cmd.CmdTypeGet: { { - Description: "Inspect an instance template by name or UUID", + Description: "Inspect an instance template by name", Commands: []string{"unikraft instance template get demo-template"}, }, + { + Description: "Inspect an instance template by UUID", + Commands: []string{"unikraft instance template get d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Show template details in JSON format", + Commands: []string{"unikraft instance template get demo-template -o json"}, + }, }, cmd.CmdTypeList: { { Description: "List instance templates across metros", Commands: []string{"unikraft instance template list"}, }, + { + Description: "List templates in table format", + Commands: []string{"unikraft instance template list -o table"}, + }, }, cmd.CmdTypeCreate: { { Description: "Convert a stopped instance into a template", Commands: []string{"unikraft instance template create demo-instance"}, }, + { + Description: "Convert multiple instances into templates", + Commands: []string{"unikraft instance template create instance-1 instance-2"}, + }, }, cmd.CmdTypeEdit: { { Description: "Update template tags", Commands: []string{ - "unikraft instance template edit demo-template --set tags=env-dev", + "unikraft instance template edit demo-template --tags env-prod,team-platform", + }, + }, + { + Description: "Lock a template to prevent deletion", + Commands: []string{ + "unikraft instance template edit demo-template --delete-lock", }, }, }, @@ -441,6 +463,10 @@ func (InstanceTemplate) Examples() map[cmd.CmdType][]kingkong.Example { Description: "Delete an instance template", Commands: []string{"unikraft instance template delete demo-template"}, }, + { + Description: "Delete all instance templates (with confirmation)", + Commands: []string{"unikraft instance template delete --all"}, + }, }, } } diff --git a/internal/cmd/instances.go b/internal/cmd/instances.go index 3d0fdf48..1f58275e 100644 --- a/internal/cmd/instances.go +++ b/internal/cmd/instances.go @@ -918,34 +918,60 @@ func (Instance) Examples() map[cmd.CmdType][]kingkong.Example { return map[cmd.CmdType][]kingkong.Example{ cmd.CmdTypeGet: { { - Description: "Inspect an instance by name or UUID", + Description: "Inspect an instance by name", Commands: []string{"unikraft instance get demo-instance"}, }, + { + Description: "Inspect an instance by UUID", + Commands: []string{"unikraft instance get d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Inspect an instance in a specific metro", + Commands: []string{"unikraft instance get fra/demo-instance"}, + }, + { + Description: "Show instance details in JSON format", + Commands: []string{"unikraft instance get demo-instance -o json"}, + }, + { + Description: "Watch instance state changes in real-time", + Commands: []string{"unikraft instance get demo-instance -w"}, + }, }, cmd.CmdTypeList: { { - Description: "List instances across metros", + Description: "List instances across all metros", Commands: []string{"unikraft instance list"}, }, + { + Description: "List only running instances", + Commands: []string{`unikraft instance list --filter 'state=="running"'`}, + }, + { + Description: "List instances sorted by creation time (newest first)", + Commands: []string{"unikraft instance list --sort -timestamps.created"}, + }, + { + Description: "Watch instances and refresh every 5 seconds", + Commands: []string{"unikraft instance list -w 5s"}, + }, + { + Description: "List instances as a table with additional fields", + Commands: []string{"unikraft instance list -f +resources -o table"}, + }, }, cmd.CmdTypeCreate: { { - Description: "Create a new instance", + Description: "Create a new instance with HTTPS port exposed", Commands: []string{ - // `unikraft instance create \ - // --set name=demo-instance \ - // --set metro=fra \ - // --set image=nginx:latest \ - // --set autostart=true \ - // --set resources.memory=128 \ - // --set resources.vcpus=1`, `unikraft instance create \ --name demo-instance \ --metro fra \ --image nginx:latest \ --autostart \ - --memory 128 \ - --vcpus 1`, + -m 128MiB \ + --vcpus 1 \ + -p 443:8080/http+tls`, }, }, { @@ -957,21 +983,94 @@ func (Instance) Examples() map[cmd.CmdType][]kingkong.Example { --template my-template`, }, }, + { + Description: "Create an instance with environment variables and a volume", + Commands: []string{ + `unikraft instance create \ + --metro sfo \ + --image my-app:latest \ + -e DB_HOST=db.example.com \ + -e DB_PORT=5432 \ + -v data-vol:/data \ + --autostart`, + }, + }, + { + Description: "Create an instance with scale-to-zero enabled", + Commands: []string{ + `unikraft instance create \ + --metro fra \ + --image my-app:latest \ + --scale-to-zero policy=on,cooldown-time=300 \ + -p 443:8080/http+tls \ + --autostart`, + }, + }, + { + Description: "Preview instance creation without applying", + Commands: []string{ + `unikraft instance create \ + --metro dal \ + --image nginx:latest \ + --dry-run`, + }, + }, + { + Description: "Save creatable fields to a YAML file for later use", + Commands: []string{ + "unikraft instance create --save instance.yaml --dry-run", + }, + }, }, cmd.CmdTypeEdit: { { Description: "Resize instance memory", Commands: []string{ - // "unikraft instance edit demo-instance --set resources.memory=256", - "unikraft instance edit demo-instance --memory 256", + "unikraft instance edit demo-instance -m 256MiB", + }, + }, + { + Description: "Update the image of an instance", + Commands: []string{ + "unikraft instance edit demo-instance --image my-app:v2.0", + }, + }, + { + Description: "Change environment variables", + Commands: []string{ + "unikraft instance edit demo-instance --set runtime.env.DEBUG=true", + }, + }, + { + Description: "Enable scale-to-zero on an existing instance", + Commands: []string{ + "unikraft instance edit demo-instance --scale-to-zero on", + }, + }, + { + Description: "Preview edits without applying them", + Commands: []string{ + "unikraft instance edit demo-instance -m 512MiB --dry-run", }, }, }, cmd.CmdTypeDelete: { { - Description: "Delete an instance by name or UUID", + Description: "Delete an instance by name", Commands: []string{"unikraft instance delete demo-instance"}, }, + { + Description: "Delete an instance by UUID", + Commands: []string{"unikraft instance delete d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Delete multiple instances at once", + Commands: []string{"unikraft instance delete instance-1 instance-2"}, + }, + { + Description: "Delete all stopped instances (with confirmation)", + Commands: []string{`unikraft instance delete --filter 'state=="stopped"'`}, + }, }, } } @@ -993,7 +1092,7 @@ func (cmd InstancesLogsCmd) Examples() []kingkong.Example { }, }, { - Description: "Fetch the last 100 lines of logs from an instance", + Description: "Fetch the last 100 lines of logs", Commands: []string{ "unikraft instance logs my-instance --tail 100", }, @@ -1004,6 +1103,24 @@ func (cmd InstancesLogsCmd) Examples() []kingkong.Example { "unikraft instance logs my-instance --follow", }, }, + { + Description: "Fetch logs from a specific metro", + Commands: []string{ + "unikraft instance logs fra/my-instance", + }, + }, + { + Description: "Follow logs from multiple instances", + Commands: []string{ + "unikraft instance logs instance-1 instance-2 --follow", + }, + }, + { + Description: "Follow logs without instance name prefix", + Commands: []string{ + "unikraft instance logs my-instance --follow --no-prefix", + }, + }, } } @@ -1075,6 +1192,18 @@ func (cmd InstancesStartCmd) Examples() []kingkong.Example { "unikraft instance start demo-instance", }, }, + { + Description: "Start multiple instances at once", + Commands: []string{ + "unikraft instance start instance-1 instance-2 instance-3", + }, + }, + { + Description: "Start an instance in a specific metro", + Commands: []string{ + "unikraft instance start fra/demo-instance", + }, + }, } } @@ -1135,23 +1264,29 @@ type InstancesStopCmd struct { func (cmd InstancesStopCmd) Examples() []kingkong.Example { return []kingkong.Example{ { - Description: "Stop an instance", + Description: "Stop an instance gracefully", Commands: []string{ "unikraft instance stop demo-instance", }, }, { - Description: "Stop with a drain timeout", + Description: "Stop with a drain timeout to allow in-flight requests to complete", Commands: []string{ "unikraft instance stop demo-instance --drain-timeout 30000", }, }, { - Description: "Force stop an instance", + Description: "Force stop an instance immediately", Commands: []string{ "unikraft instance stop demo-instance --force", }, }, + { + Description: "Stop multiple instances", + Commands: []string{ + "unikraft instance stop instance-1 instance-2", + }, + }, } } @@ -1211,17 +1346,23 @@ type InstancesRestartCmd struct { func (cmd InstancesRestartCmd) Examples() []kingkong.Example { return []kingkong.Example{ { - Description: "Restart an instance", + Description: "Restart an instance gracefully", Commands: []string{ "unikraft instance restart demo-instance", }, }, { - Description: "Force restart an instance", + Description: "Force restart an instance (skips graceful shutdown)", Commands: []string{ "unikraft instance restart demo-instance --force", }, }, + { + Description: "Restart with a drain timeout", + Commands: []string{ + "unikraft instance restart demo-instance --drain-timeout 10000", + }, + }, } } @@ -1362,17 +1503,23 @@ type InstancesSuspendCmd struct { func (cmd InstancesSuspendCmd) Examples() []kingkong.Example { return []kingkong.Example{ { - Description: "Suspend an instance", + Description: "Suspend an instance (preserves state for fast resume)", Commands: []string{ "unikraft instance suspend demo-instance", }, }, { - Description: "Suspend with a drain timeout", + Description: "Suspend with a drain timeout to allow in-flight requests to complete", Commands: []string{ "unikraft instance suspend demo-instance --drain-timeout 30000", }, }, + { + Description: "Suspend multiple instances", + Commands: []string{ + "unikraft instance suspend instance-1 instance-2", + }, + }, } } diff --git a/internal/cmd/metros.go b/internal/cmd/metros.go index 3b7f073e..2d6a841f 100644 --- a/internal/cmd/metros.go +++ b/internal/cmd/metros.go @@ -239,6 +239,10 @@ func (Metro) Examples() map[cmd.CmdType][]kingkong.Example { Description: "Inspect a metro by name", Commands: []string{"unikraft metro get fra"}, }, + { + Description: "Show all metro details including status and quotas", + Commands: []string{"unikraft metro get fra -f +status,+quotas"}, + }, }, cmd.CmdTypeList: { { @@ -246,13 +250,17 @@ func (Metro) Examples() map[cmd.CmdType][]kingkong.Example { Commands: []string{"unikraft metro list"}, }, { - Description: "List metros with connection status", + Description: "List metros with latency and online status", Commands: []string{"unikraft metro list -f +status"}, }, { Description: "List metros with quota usage", Commands: []string{"unikraft metro list -f +quotas"}, }, + { + Description: "Output metro list as JSON", + Commands: []string{"unikraft metro list -o json"}, + }, }, } } diff --git a/internal/cmd/profile.go b/internal/cmd/profile.go index 8bfc5c46..bef7fbd3 100644 --- a/internal/cmd/profile.go +++ b/internal/cmd/profile.go @@ -91,12 +91,20 @@ func (Profile) Examples() map[cmd.CmdType][]kingkong.Example { Description: "Inspect a profile by name", Commands: []string{"unikraft profile get default"}, }, + { + Description: "Show the currently active profile", + Commands: []string{`unikraft profile list --filter 'active==true'`}, + }, }, cmd.CmdTypeList: { { Description: "List all profiles", Commands: []string{"unikraft profile list"}, }, + { + Description: "List profiles in JSON format", + Commands: []string{"unikraft profile list -o json"}, + }, }, } } diff --git a/internal/cmd/root.go b/internal/cmd/root.go index b2573bd4..251ba32d 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -71,9 +71,9 @@ func (cli UnikraftCLI) Examples() []kingkong.Example { }, }, { - Description: "List instances across metros", + Description: "List instances across all metros", Commands: []string{ - "unikraft instances list", + "unikraft instance list", }, }, { @@ -85,7 +85,13 @@ func (cli UnikraftCLI) Examples() []kingkong.Example { { Description: "Deploy a new instance from an image", Commands: []string{ - "unikraft run --metro=sfo --image=nginx:latest --autostart -p 443:8080/http+tls --scale-to-zero policy=on", + "unikraft run --metro=fra --image=nginx:latest -p 443:8080/http+tls --scale-to-zero on", + }, + }, + { + Description: "Browse resources in an interactive TUI", + Commands: []string{ + "unikraft tui", }, }, { diff --git a/internal/cmd/run.go b/internal/cmd/run.go index a2cfd0f2..e81e5830 100644 --- a/internal/cmd/run.go +++ b/internal/cmd/run.go @@ -36,19 +36,19 @@ type RunCmd struct { func (RunCmd) Examples() []kingkong.Example { return []kingkong.Example{ { - Description: "Deploy a new instance and expose a HTTPS service", + Description: "Deploy a new instance and expose an HTTPS service", Commands: []string{ - "unikraft run --metro=sfo --image=nginx:latest -p 443:8080/http+tls", + "unikraft run --metro=fra --image=nginx:latest -p 443:8080/http+tls", }, }, { - Description: "Deploy a new instance and expose a HTTPS service and redirect from HTTP to HTTPS", + Description: "Deploy with HTTPS and HTTP-to-HTTPS redirect", Commands: []string{ - "unikraft run --metro=sfo --image=nginx:latest -p 443:8080/http+tls -p 80:443/http+redirect", + "unikraft run --metro=fra --image=nginx:latest -p 443:8080/http+tls -p 80:443/http+redirect", }, }, { - Description: "Deploy and tail logs from a new instance", + Description: "Deploy and tail logs", Commands: []string{ "unikraft run --metro=fra --image=nginx:latest --follow", }, @@ -56,43 +56,52 @@ func (RunCmd) Examples() []kingkong.Example { { Description: "Preview instance creation without executing", Commands: []string{ - "unikraft run --metro=dal --image=nginx:latest --dry-run", + "unikraft run --metro=fra --image=nginx:latest --dry-run", }, }, { - Description: "Deploy a new instance with environment variables", + Description: "Deploy with environment variables", Commands: []string{ - "unikraft run --metro=was --image=my-app:latest -e KEY1=VALUE1 -e KEY2=VALUE2", + "unikraft run --metro=fra --image=my-app:latest -e KEY1=VALUE1 -e KEY2=VALUE2", }, }, { - Description: "Deploy a new instance with attached volume", + Description: "Deploy with an attached volume", Commands: []string{ - "unikraft run --metro=sin --image=my-app:latest -v my-volume:/data", + "unikraft run --metro=fra --image=my-app:latest -v my-volume:/data", }, }, { - Description: "Deploy a new instance with attached volume which is read-only", + Description: "Deploy with a read-only volume", Commands: []string{ - "unikraft run --metro=sin --image=my-app:latest -v my-volume:/data:ro", + "unikraft run --metro=fra --image=my-app:latest -v config-vol:/etc/app:ro", }, }, { - Description: "Deploy a new instance with custom resource allocations", + Description: "Deploy with custom resource allocations", Commands: []string{ - "unikraft run --metro=sfo --image=my-app:latest -m 512MiB --vcpus 2", + "unikraft run --metro=fra --image=my-app:latest -m 512MiB --vcpus 2", }, }, { - Description: "Deploy a new instance with scale-to-zero enabled", + Description: "Deploy with scale-to-zero enabled", Commands: []string{ - "unikraft run --metro=fra --image=my-app:latest --scale-to-zero policy=on,cooldown-time=300", + "unikraft run --metro=fra --image=my-app:latest --scale-to-zero on -p 443:8080/http+tls", }, }, { - Description: "Deploy a new instance with specific restart policy", + Description: "Deploy with a custom restart policy", Commands: []string{ - "unikraft run --metro=dal --image=my-app:latest --restart=on-failure", + "unikraft run --metro=fra --image=my-app:latest --restart=on-failure", + }, + }, + { + Description: "Deploy a named instance with a custom domain", + Commands: []string{ + `unikraft run --metro=fra --image=my-app:latest \ + --name my-web-app \ + -p 443:8080/http+tls \ + --domain my-app.example.com`, }, }, } diff --git a/internal/cmd/services.go b/internal/cmd/services.go index f57764ce..58add5e1 100644 --- a/internal/cmd/services.go +++ b/internal/cmd/services.go @@ -471,30 +471,73 @@ func (ServiceGroup) Examples() map[cmd.CmdType][]kingkong.Example { return map[cmd.CmdType][]kingkong.Example{ cmd.CmdTypeGet: { { - Description: "Inspect a service group by name or UUID", + Description: "Inspect a service group by name", Commands: []string{"unikraft service get demo-service"}, }, + { + Description: "Inspect a service group by UUID", + Commands: []string{"unikraft service get d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Inspect a service group in a specific metro", + Commands: []string{"unikraft service get fra/demo-service"}, + }, + { + Description: "Show service details in JSON format", + Commands: []string{"unikraft service get demo-service -o json"}, + }, }, cmd.CmdTypeList: { { - Description: "List all service groups", + Description: "List all service groups across metros", Commands: []string{"unikraft service list"}, }, + { + Description: "List services and watch for changes", + Commands: []string{"unikraft service list -w"}, + }, }, cmd.CmdTypeCreate: { { - Description: "Create a new service group", + Description: "Create a service group with HTTPS", Commands: []string{ - // `unikraft service create \ - // --set name=demo-service \ - // --set metro=fra \ - // --set domains=demo \ - // --set services=443:8080/tls+http`, `unikraft service create \ --name demo-service \ --metro fra \ --domains demo \ - --services 443:8080/tls+http`, + --services 443:8080/http+tls`, + }, + }, + { + Description: "Create a service group with HTTPS and HTTP-to-HTTPS redirect", + Commands: []string{ + `unikraft service create \ + --name web-service \ + --metro fra \ + --domains my-app.example.com \ + --services 443:8080/http+tls \ + --services 80:443/http+redirect`, + }, + }, + { + Description: "Create a service group with rate limits", + Commands: []string{ + `unikraft service create \ + --name api-service \ + --metro fra \ + --services 443:8080/http+tls \ + --soft-limit 100 \ + --hard-limit 200`, + }, + }, + { + Description: "Preview service creation without applying", + Commands: []string{ + `unikraft service create \ + --name test-service \ + --metro fra \ + --services 443:8080/http+tls \ + --dry-run`, }, }, }, @@ -502,16 +545,41 @@ func (ServiceGroup) Examples() map[cmd.CmdType][]kingkong.Example { { Description: "Add a new service port", Commands: []string{ - // "unikraft service edit demo-service --add services=8443:8080/tls", - "unikraft service edit demo-service --services 8443:8080/tls", + "unikraft service edit demo-service --add services=8443:9090/http+tls", + }, + }, + { + Description: "Add a domain to a service group", + Commands: []string{ + "unikraft service edit demo-service --add domains=api.example.com", + }, + }, + { + Description: "Update rate limits", + Commands: []string{ + "unikraft service edit demo-service --soft-limit 50 --hard-limit 100", + }, + }, + { + Description: "Remove a domain from a service group", + Commands: []string{ + "unikraft service edit demo-service --del domains=old.example.com", }, }, }, cmd.CmdTypeDelete: { { - Description: "Delete a service group by name or UUID", + Description: "Delete a service group by name", Commands: []string{"unikraft service delete demo-service"}, }, + { + Description: "Delete a service group by UUID", + Commands: []string{"unikraft service delete d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Delete all service groups (with confirmation)", + Commands: []string{"unikraft service delete --all"}, + }, }, } } diff --git a/internal/cmd/tui.go b/internal/cmd/tui.go index 7c20d294..3d0cc693 100644 --- a/internal/cmd/tui.go +++ b/internal/cmd/tui.go @@ -15,6 +15,7 @@ import ( "unikraft.com/cli/internal/resource" resourcetui "unikraft.com/cli/internal/resource/tui" "unikraft.com/cli/internal/tui/uitui" + "unikraft.com/x/kingkong" ) type TUICmd struct { @@ -22,6 +23,27 @@ type TUICmd struct { Name string `arg:"" optional:"" help:"Resource key to open."` } +func (TUICmd) Examples() []kingkong.Example { + return []kingkong.Example{ + { + Description: "Open the TUI home screen", + Commands: []string{"unikraft tui"}, + }, + { + Description: "Browse instances directly", + Commands: []string{"unikraft tui instances"}, + }, + { + Description: "Open a specific instance detail view", + Commands: []string{"unikraft tui instances demo-instance"}, + }, + { + Description: "Browse volumes", + Commands: []string{"unikraft tui volumes"}, + }, + } +} + // NewTUIModel builds the same Bubble Tea model used by `unikraft tui`. func NewTUIModel(ctx context.Context, resourceArg, nameArg string) (tea.Model, error) { registry := resource.NewRegistry() diff --git a/internal/cmd/upgrade.go b/internal/cmd/upgrade.go index 409bf41a..1ef7582d 100644 --- a/internal/cmd/upgrade.go +++ b/internal/cmd/upgrade.go @@ -22,6 +22,7 @@ import ( jujuerrors "github.com/juju/errors" "golang.org/x/mod/semver" + "unikraft.com/x/kingkong" "unikraft.com/x/log" "unikraft.com/cli/internal/binorigin" @@ -42,6 +43,27 @@ type UpgradeCmd struct { BaseUrl string `help:"Base URL for fetching releases." env:"UNIKRAFT_CLI_INSTALL_URL" default:"https://pkg.unikraft.com" hidden:"true"` } +func (UpgradeCmd) Examples() []kingkong.Example { + return []kingkong.Example{ + { + Description: "Upgrade to the latest stable version", + Commands: []string{"unikraft upgrade"}, + }, + { + Description: "Upgrade to a specific version", + Commands: []string{"unikraft upgrade --version v1.2.3"}, + }, + { + Description: "Upgrade from the staging channel", + Commands: []string{"unikraft upgrade --channel staging"}, + }, + { + Description: "Force re-install even if already at the latest version", + Commands: []string{"unikraft upgrade --force"}, + }, + } +} + func (cmd *UpgradeCmd) Run(ctx context.Context, stdio config.Stdio) error { // Detect if running with sudo and warn if os.Getenv("SUDO_UID") != "" || os.Getenv("SUDO_GID") != "" || os.Getenv("SUDO_USER") != "" { diff --git a/internal/cmd/volume_templates.go b/internal/cmd/volume_templates.go index f0888e96..73fd6004 100644 --- a/internal/cmd/volume_templates.go +++ b/internal/cmd/volume_templates.go @@ -395,9 +395,17 @@ func (VolumeTemplate) Examples() map[cmd.CmdType][]kingkong.Example { return map[cmd.CmdType][]kingkong.Example{ cmd.CmdTypeGet: { { - Description: "Inspect a volume template by name or UUID", + Description: "Inspect a volume template by name", Commands: []string{"unikraft volume template get demo-template"}, }, + { + Description: "Inspect a volume template by UUID", + Commands: []string{"unikraft volume template get d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Show template details in JSON format", + Commands: []string{"unikraft volume template get demo-template -o json"}, + }, }, cmd.CmdTypeList: { { @@ -410,12 +418,22 @@ func (VolumeTemplate) Examples() map[cmd.CmdType][]kingkong.Example { Description: "Convert a volume into a template", Commands: []string{"unikraft volume template create demo-volume"}, }, + { + Description: "Convert multiple volumes into templates", + Commands: []string{"unikraft volume template create vol-1 vol-2"}, + }, }, cmd.CmdTypeEdit: { { Description: "Update template tags", Commands: []string{ - "unikraft volume template edit demo-template --set tags=env-dev", + "unikraft volume template edit demo-template --tags env-prod,team-data", + }, + }, + { + Description: "Lock a template to prevent deletion", + Commands: []string{ + "unikraft volume template edit demo-template --delete-lock", }, }, }, @@ -424,6 +442,10 @@ func (VolumeTemplate) Examples() map[cmd.CmdType][]kingkong.Example { Description: "Delete a volume template", Commands: []string{"unikraft volume template delete demo-template"}, }, + { + Description: "Delete all volume templates (with confirmation)", + Commands: []string{"unikraft volume template delete --all"}, + }, }, } } diff --git a/internal/cmd/volumes.go b/internal/cmd/volumes.go index ca5dfb00..3017ca40 100644 --- a/internal/cmd/volumes.go +++ b/internal/cmd/volumes.go @@ -109,10 +109,15 @@ func (VolumesCloneCmd) Examples() []kingkong.Example { { Description: "Clone a volume with a new name", Commands: []string{ - // "unikraft volume clone demo-volume --set name=demo-volume-clone", "unikraft volume clone demo-volume --name demo-volume-clone", }, }, + { + Description: "Clone a volume with tags", + Commands: []string{ + "unikraft volume clone demo-volume --name backup --tags env=staging", + }, + }, } } @@ -515,45 +520,94 @@ func (Volume) Examples() map[cmd.CmdType][]kingkong.Example { return map[cmd.CmdType][]kingkong.Example{ cmd.CmdTypeGet: { { - Description: "Inspect a volume by name or UUID", + Description: "Inspect a volume by name", Commands: []string{"unikraft volume get demo-volume"}, }, + { + Description: "Inspect a volume by UUID", + Commands: []string{"unikraft volume get d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Inspect a volume in a specific metro", + Commands: []string{"unikraft volume get fra/demo-volume"}, + }, + { + Description: "Show volume details in JSON format", + Commands: []string{"unikraft volume get demo-volume -o json"}, + }, }, cmd.CmdTypeList: { { - Description: "List all volumes", + Description: "List all volumes across metros", Commands: []string{"unikraft volume list"}, }, + { + Description: "List volumes and watch for state changes", + Commands: []string{"unikraft volume list -w"}, + }, + { + Description: "List volumes with attachment information", + Commands: []string{"unikraft volume list -f +attached-to"}, + }, }, cmd.CmdTypeCreate: { { - Description: "Create a new volume", + Description: "Create a 10 GiB volume", Commands: []string{ - // `unikraft volume create \ - // --set name=demo-volume \ - // --set size=10 \ - // --set metro=fra`, `unikraft volume create \ --name demo-volume \ - --size 10 \ + --size 10GiB \ --metro fra`, }, }, + { + Description: "Create a volume with ext4 filesystem", + Commands: []string{ + `unikraft volume create \ + --name app-data \ + --size 5GiB \ + --filesystem ext4 \ + --metro fra`, + }, + }, + { + Description: "Preview volume creation without applying", + Commands: []string{ + `unikraft volume create \ + --name test-vol \ + --size 1GiB \ + --metro fra \ + --dry-run`, + }, + }, }, cmd.CmdTypeEdit: { { Description: "Resize a volume", Commands: []string{ - // "unikraft volume edit demo-volume --set size=20", - "unikraft volume edit demo-volume --size 20", + "unikraft volume edit demo-volume --size 20GiB", + }, + }, + { + Description: "Change the quota policy", + Commands: []string{ + "unikraft volume edit demo-volume --quota-policy dynamic", }, }, }, cmd.CmdTypeDelete: { { - Description: "Delete a volume by name or UUID", + Description: "Delete a volume by name", Commands: []string{"unikraft volume delete demo-volume"}, }, + { + Description: "Delete a volume by UUID", + Commands: []string{"unikraft volume delete d4f0c132-a70e-4777-9631-7dfe08a1c15d"}, + }, + { + Description: "Delete all volumes (with confirmation)", + Commands: []string{"unikraft volume delete --all"}, + }, }, } } @@ -600,6 +654,10 @@ func (VolumeImportCmd) Examples() []kingkong.Example { Description: "Import a Dockerfile context into a volume", Commands: []string{"unikraft volume import my-volume --source ./Dockerfile"}, }, + { + Description: "Force import even if data exceeds volume capacity", + Commands: []string{"unikraft volume import my-volume --source ./large-data --force"}, + }, } }