cli

package
v1.786.92 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package cli is the Hanzo cloud-control CLI — the gcloud/doctl-class client half of the `hanzo` binary.

`hanzo <subsystem>` SERVES a subsystem (server mode, cmd/hanzo dispatch); `hanzo <verb>` CONTROLS the live estate (client mode, this package):

hanzo login | auth        identity against hanzo.id (IAM)
hanzo apps  list|get      the platform apps board (declared/running/drift)
hanzo deploy              drive a platform redeploy (rolling, zero-downtime)
hanzo clusters …          provision/list/select dedicated DOKS clusters
hanzo build               enqueue a platform-native (arcd) build
hanzo k8s …               current deploy target helpers
hanzo config …            ~/.hanzo/config preferences

It is a THIN client over surfaces that already exist — Hanzo IAM (hanzo.id /v1/iam/oauth/*), the platform REST control plane (platform.hanzo.ai /v1/*), and the cloud /v1 API. It invents no parallel API and holds no business logic; every command is one HTTP call shaped by resolved configuration. Secrets live only in ~/.hanzo (0600) or the environment — never in source, never logged.

Index

Constants

This section is empty.

Variables

View Source
var Version = "dev"

Version is the binary version, set by cmd/hanzo from its -ldflags value so the CLI and the server report one string. Used in the User-Agent.

Functions

func ControlCommands

func ControlCommands() map[string]string

ControlCommands returns the verb→description map for `hanzo help`.

func DeleteCredentials

func DeleteCredentials() error

DeleteCredentials removes the credential store (used by logout).

func Execute

func Execute(args []string) error

Execute runs the control CLI with args (already stripped of "hanzo"). It is the single entrypoint cmd/hanzo calls for client-mode verbs.

func IsControlVerb

func IsControlVerb(sub string) bool

IsControlVerb reports whether sub is a client-mode command (and therefore must be routed to this package, not the server dispatcher).

func RestoreStdout

func RestoreStdout()

RestoreStdout restores the real process stdout. cmd/hanzo calls this as its first statement so every command writes to the genuine stdout.

Types

type AppView

type AppView struct {
	ID            string          `json:"id"`
	Org           string          `json:"org"`
	App           string          `json:"app"`
	Env           string          `json:"env"`
	Repo          string          `json:"repo"`
	Registry      string          `json:"registry"`
	DeclaredTag   *string         `json:"declaredTag"`
	RunningTag    *string         `json:"runningTag"`
	LatestTag     *string         `json:"latestTag"`
	ReleaseURL    *string         `json:"releaseUrl"`
	ReleaseAssets int             `json:"releaseAssets"`
	Health        *string         `json:"health"`
	Cluster       *string         `json:"cluster"`
	Namespace     *string         `json:"namespace"`
	LastObserved  *string         `json:"lastObserved"`
	UpdatedAt     string          `json:"updatedAt"`
	Drift         json.RawMessage `json:"drift"`
}

AppView mirrors the platform apps-lifecycle DTO. Nullable columns are *string so JSON null round-trips; Drift is kept raw so --json is byte-faithful and the drift schema can evolve without a client bump.

type AppsList

type AppsList struct {
	Apps    []AppView `json:"apps"`
	Summary struct {
		Total   int            `json:"total"`
		ByDrift map[string]int `json:"byDrift"`
	} `json:"summary"`
}

AppsList is the /v1/apps envelope: ordered rows + a drift summary.

type AppsQuery

type AppsQuery struct {
	Org    string
	Env    string
	Health string
	Drift  bool
}

AppsQuery are the optional /v1/apps filters.

type BuildJob

type BuildJob struct {
	BuildJobID string `json:"buildJobId"`
	Status     string `json:"status"`
	RunnerPool string `json:"runnerPool"`
	Image      string `json:"image"`
	Target     string `json:"target"`
}

BuildJob is the enqueue acceptance (HTTP 202).

type BuildReq

type BuildReq struct {
	Repo           string `json:"repo"`
	SHA            string `json:"sha"`
	Image          string `json:"image"`
	Branch         string `json:"branch,omitempty"`
	Ref            string `json:"ref,omitempty"`
	Dockerfile     string `json:"dockerfile,omitempty"`
	Context        string `json:"context,omitempty"`
	DockerTarget   string `json:"dockerTarget,omitempty"`
	OS             string `json:"os,omitempty"`
	Arch           string `json:"arch,omitempty"`
	OrganizationID string `json:"organizationId,omitempty"`
}

BuildReq is the direct-enqueue body. Repo/SHA/Image are required.

type Cluster

type Cluster struct {
	DoksClusterID     string          `json:"doksClusterId"`
	Name              string          `json:"name"`
	DoClusterID       *string         `json:"doClusterId"`
	Region            string          `json:"region"`
	Status            string          `json:"status"`
	Endpoint          *string         `json:"endpoint"`
	K8sVersion        *string         `json:"k8sVersion"`
	HA                bool            `json:"ha"`
	Phase             string          `json:"phase"`
	OperatorInstalled bool            `json:"operatorInstalled"`
	BaselineInstalled bool            `json:"baselineInstalled"`
	Active            bool            `json:"active"`
	BaselineError     *string         `json:"baselineError"`
	OrganizationID    string          `json:"organizationId"`
	CreatedAt         string          `json:"createdAt"`
	Tags              []string        `json:"tags"`
	MaintenancePolicy json.RawMessage `json:"maintenancePolicy,omitempty"`
}

Cluster mirrors a doks_cluster record. `status` is DigitalOcean state; `phase` is the platform provisioning lifecycle — orthogonal (a DO-running cluster is not a usable target until phase=ready).

type Config

type Config struct {
	Org         string `json:"org,omitempty"`
	Output      string `json:"output,omitempty"` // "table" (default) | "json"
	IAMIssuer   string `json:"iam_issuer,omitempty"`
	PlatformURL string `json:"platform_url,omitempty"`
	CloudURL    string `json:"cloud_url,omitempty"`
	ClientID    string `json:"client_id,omitempty"`
}

Config holds non-secret CLI preferences. Every field is optional; empty fields fall back to the built-in defaults at resolution time.

func LoadConfig

func LoadConfig() (*Config, error)

LoadConfig reads ~/.hanzo/config (or HANZO_CONFIG).

func (*Config) Save

func (c *Config) Save() error

Save persists the config (mode 0644 — non-secret).

type Credentials

type Credentials struct {
	AccessToken   string `json:"access_token,omitempty"`
	RefreshToken  string `json:"refresh_token,omitempty"`
	TokenType     string `json:"token_type,omitempty"`
	Expiry        int64  `json:"expiry,omitempty"` // unix seconds
	Subject       string `json:"subject,omitempty"`
	Owner         string `json:"owner,omitempty"` // org slug from the token
	PlatformToken string `json:"platform_token,omitempty"`
	BuildToken    string `json:"build_token,omitempty"`
}

Credentials holds secret material, ~/.hanzo/credentials.json, mode 0600. AccessToken/RefreshToken are the IAM user identity (from `hanzo login`); PlatformToken/BuildToken are the machine-to-machine tokens the platform REST control plane requires (it cannot validate IAM user tokens).

func LoadCredentials

func LoadCredentials() (*Credentials, error)

LoadCredentials reads ~/.hanzo/credentials.json.

func (*Credentials) Save

func (c *Credentials) Save() error

Save persists credentials with mode 0600 (owner read/write only).

type Env

type Env struct {
	Org         string
	Output      string
	IAMIssuer   string
	PlatformURL string
	CloudURL    string
	ClientID    string
	// contains filtered or unexported fields
}

Env is the fully-resolved runtime context for a command: config + creds merged with environment and the global flags. Built once in the root's PersistentPreRunE and read by every subcommand.

type Platform

type Platform struct {
	// contains filtered or unexported fields
}

Platform is a thin client over the platform.hanzo.ai /v1 control plane. That surface is machine-to-machine (service-token, "No OIDC" — it cannot validate IAM user tokens), so the token here is the platform service token, resolved from flag/env/credential store by the caller; the build endpoint takes its own token per call.

func (*Platform) App

func (p *Platform) App(ctx context.Context, id, org string) (*AppView, error)

func (*Platform) Apps

func (p *Platform) Apps(ctx context.Context, q AppsQuery) (*AppsList, error)

func (*Platform) Clusters

func (p *Platform) Clusters(ctx context.Context, org string) ([]Cluster, error)

func (*Platform) EnqueueBuild

func (p *Platform) EnqueueBuild(ctx context.Context, req BuildReq, buildToken string) (*BuildJob, error)

EnqueueBuild enqueues a native build. It authenticates with the dedicated build-callback token, not the service token.

func (*Platform) InstallBaseline

func (p *Platform) InstallBaseline(ctx context.Context, org, clusterID string) error

func (*Platform) ProvisionCluster

func (p *Platform) ProvisionCluster(ctx context.Context, org string, req ProvisionReq) (*Cluster, error)

func (*Platform) Redeploy

func (p *Platform) Redeploy(ctx context.Context, org, project, env, container string) error

Redeploy triggers a rolling restart of the container's k8s Deployment. The coordinates are exact (the platform validates org+project+env+container scope).

func (*Platform) SelectTarget

func (p *Platform) SelectTarget(ctx context.Context, org string, clusterID *string) (*Target, error)

SelectTarget activates a dedicated cluster as the org's deploy target, or reverts to the shared cluster when clusterID is nil.

func (*Platform) SyncApps

func (p *Platform) SyncApps(ctx context.Context) error

func (*Platform) Target

func (p *Platform) Target(ctx context.Context, org string) (*Target, error)

type ProvisionReq

type ProvisionReq struct {
	Region    string `json:"region,omitempty"`
	HA        bool   `json:"ha,omitempty"`
	NodeSize  string `json:"nodeSize,omitempty"`
	NodeCount int    `json:"nodeCount,omitempty"`
}

ProvisionReq is the dedicated-cluster provisioning body (org forced by path).

type Target

type Target struct {
	Cluster    string            `json:"cluster"`
	Namespaces map[string]string `json:"namespaces"`
	Dedicated  bool              `json:"dedicated"`
}

Target is the redacted ClusterTargetView — the kubeconfig is never present.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL