You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
🤖 Generated with Claude Code in an interactive session with the maintainer.
User Story
As a KSail user targeting AWS, I wantksail cluster create --distribution EKS to work with nothing installed but KSail itself, So that EKS behaves like every other distribution instead of being the one that fails at the PATH lookup.
Context
KSail's stated contract is that it embeds its tooling as Go libraries: "Docker is the only required external dependency for local clusters". EKS is the single exception — pkg/svc/provisioner/cluster/eks shells out to an eksctl binary via pkg/client/eksctl, and pkg/apis/cluster/v1alpha1.ErrEksctlBinaryMissing is the error users hit when it is absent. GKE and AKS already use their native Go SDKs (pkg/client/gke, pkg/client/aks), so EKS is the odd one out in its own package family.
This is a migration, not a restart.#4328 is at 16/18 sub-issues and the native path is already half-built — this epic finishes the direction that repo has been travelling, it does not reverse it:
pkg/client/eks is already an AWS SDK v2 client doing DescribeCluster, EKS bearer-token minting (presigned STS GetCallerIdentity), nodegroup reads, and CloudFormation stack checks.
The control-plane upgrade already moved off the binary.ADR 0001 replaced eksctl upgrade cluster with the SDK's UpdateClusterVersion. eksctl.Client.UpgradeCluster now has no production callers — only tests. That is dead weight today.
The SDK dependencies are already in go.mod as direct requires: aws-sdk-go-v2 core, config, credentials, cloudformation, eks, sts (iam is indirect).
What still shells out
Every remaining call lives in pkg/client/eksctl/commands.go:
pkg/svc/provisioner/cluster/eks/{creation,update,provisioner}.go · pkg/svc/provider/aws/{provider,nodegroup_state,errors}.go · pkg/svc/clusterdiscovery/{cloud,availability}.go (both gate EKS discovery on the binary being on PATH) · pkg/cli/cmd/cluster/info.go · pkg/apis/cluster/v1alpha1/errors.go · .github/workflows/system-test-eks.yaml (downloads an eksctl release) and .github/scripts/delete-eks-smoke-cluster.sh · seven pages under docs/src, plus docs/gen_docs_prose.go and AGENTS.md.
*.eksctl.iokubeconfig context parsing (pkg/svc/detector/cluster/context.go, pkg/cli/setup/localregistry/resolve.go, vsce/src/ksail/contexts.ts) is not in scope for removal — those contexts exist on every cluster the CLI ever created and must keep parsing forever.
Constraint: the eksctl declarative file stays authoritative
eks.yaml remains a valid eksctl ClusterConfig (apiVersion: eksctl.io/v1alpha5). This is non-negotiable and the migration should improve compliance, not weaken it.
Today creation.go parses the file with yaml.UnmarshalStrict into an untyped map[string]any plus a hand-rolled typed subset covering only managedNodeGroups — everything else is passed through to the binary unvalidated by KSail. The binary is currently the only thing that checks the schema.
github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5 publishes ClusterConfig along with ValidateClusterConfig, SetClusterConfigDefaults, SetNodeGroupDefaults and SetManagedNodeGroupDefaults. Adopting those types means KSail validates eks.yaml with the same code eksctl uses, so schema fidelity is guaranteed by construction rather than by re-implementation.
pkg.go.dev reports that package's import graph as light — k8s apimachinery, aws-sdk-go-v2, hashicorp/go-version, sigs.k8s.io/yaml, kris-nova/logger, and eksctl's own utils/awsapi — with nopkg/ctl, pkg/actions, kops, cfssl, kubicorn or amazon-ec2-instance-selector. That is the tree pkg/client/eksctl/doc.go cites as the reason not to embed, and it appears to apply to pkg/actions/cluster, not to the API types. Confirm with go mod graph before committing to it (#7117).
Licensing
KSail ships under PolyForm Shield 1.0.0 — source-available with a noncompete clause, not OSI-approved. That makes inbound license hygiene a real constraint rather than a formality.
eksctl (github.com/weaveworks/eksctl, still the module path) is reported by pkg.go.dev as Apache-2.0. Apache-2.0 is permissive with no copyleft, so linking it into a PolyForm-licensed binary is permitted.
The obligation is new, because shelling out distributes nothing. Today KSail ships no eksctl code. Embedding triggers Apache-2.0 §4 on every release artifact: include the license text, propagate any upstream NOTICE, retain copyright/patent notices, and mark modified files if anything is vendored or forked.
Apache-2.0 §6 grants no trademark rights. Keep "eksctl-compatible configuration" as a factual interoperability statement; never imply endorsement by eksctl, Weaveworks or AWS.
The actual risk is transitive, and it must be measured rather than assumed. A single GPL/AGPL/LGPL/SSPL/BUSL dependency reaching the linked binary is a genuine problem for a source-available product distributed via GoReleaser and Homebrew. KSail has no license scanning today — that gap is a prerequisite, not a footnote.
Migration plan
Each phase is independently shippable and leaves main releasable. Phases 2–7 become sub-issues once #7117 has sized them.
Phase 0 — cleanup and guardrail. Delete the unused UpgradeCluster shim. Add a CI license gate (go-licenses or equivalent) with an allowlist, so the dependency question is answered automatically from here on. No behaviour change.
Phase 1 — spike ([spike]: decide how KSail creates an EKS cluster without the eksctl binary #7117). Decide the create strategy: (a) import eksctl's CloudFormation template builders and drive CFN via the SDK, preserving eksctl-<cluster>-* stack names and full CLI interoperability; or (b) provision natively with EKS/EC2/IAM SDK calls, matching how pkg/client/gke and pkg/client/aks work. Output is an ADR plus follow-up issues — no PR.
Phase 2 — schema. Parse and validate eks.yaml through upstream v1alpha5 types. The binary still does the work; user-visible effect is better error messages, earlier.
Phase 3 — reads. Move get cluster / get nodegroup to the SDK. After this, ksail cluster info, cluster discovery and availability no longer need the binary at all.
Phase 5 — create and delete, behind spec.cluster.eks.experimentalNativeProvisioning, default off, per the repo's existing spec.cluster.eks.experimental* convention. The binary path stays the default.
Phase 6 — flip the default after a green live smoke run. The binary path survives one release as an opt-out.
Phase 7 — removal. Delete pkg/client/eksctl and ErrEksctlBinaryMissing, drop the eksctl download from CI, update docs and AGENTS.md.
What "non-breaking" means here
eks.yaml stays an eksctl ClusterConfig v1alpha5 — no KSail-proprietary schema, ever.
Clusters created by the eksctl CLI stay fully manageable (CloudFormation stacks, eksctl-* stack names, *.eksctl.io contexts).
The unused eksctl.Client.UpgradeCluster shim is gone.
An ADR in docs/adr/ records the create strategy and its interoperability trade-offs.
eks.yaml is parsed and validated through upstream v1alpha5 types; a malformed config is rejected by KSail with a clear error before any AWS call.
ksail cluster info, cluster discovery and availability work with no eksctl on PATH.
ksail cluster create/delete/update complete end to end with no eksctl on PATH, proven by a green live EKS smoke run.
A cluster created by the eksctl CLI is still discoverable, updatable and deletable by KSail.
pkg/client/eksctl and ErrEksctlBinaryMissing are deleted; *.eksctl.io context parsing is retained.
The eksctl download is removed from .github/workflows/system-test-eks.yaml and .github/scripts/delete-eks-smoke-cluster.sh.
Docs and AGENTS.md no longer list eksctl as a prerequisite, and the support matrix reflects the native path.
Out of scope
Completing the remaining KSail-managed component installers on EKS (#4328) and the EKS Auto Mode question. This epic changes how KSail talks to AWS, not what it installs afterwards.
User Story
As a KSail user targeting AWS,
I want
ksail cluster create --distribution EKSto work with nothing installed but KSail itself,So that EKS behaves like every other distribution instead of being the one that fails at the
PATHlookup.Context
KSail's stated contract is that it embeds its tooling as Go libraries: "Docker is the only required external dependency for local clusters". EKS is the single exception —
pkg/svc/provisioner/cluster/eksshells out to aneksctlbinary viapkg/client/eksctl, andpkg/apis/cluster/v1alpha1.ErrEksctlBinaryMissingis the error users hit when it is absent. GKE and AKS already use their native Go SDKs (pkg/client/gke,pkg/client/aks), so EKS is the odd one out in its own package family.This is a migration, not a restart. #4328 is at 16/18 sub-issues and the native path is already half-built — this epic finishes the direction that repo has been travelling, it does not reverse it:
pkg/client/eksis already an AWS SDK v2 client doingDescribeCluster, EKS bearer-token minting (presigned STSGetCallerIdentity), nodegroup reads, and CloudFormation stack checks.eksctl upgrade clusterwith the SDK'sUpdateClusterVersion.eksctl.Client.UpgradeClusternow has no production callers — only tests. That is dead weight today.go.modas direct requires:aws-sdk-go-v2core,config,credentials,cloudformation,eks,sts(iamis indirect).What still shells out
Every remaining call lives in
pkg/client/eksctl/commands.go:create cluster --config-file … --timeout 45mcreate nodegroup --config-file …CreateNodegroupdelete cluster --config-file|--name …DeleteCluster+ stack teardownget cluster [--name] -o jsonListClusters/DescribeClusterget nodegroup --cluster … -o jsonListNodegroups/DescribeNodegroupscale nodegroup --nodes …UpdateNodegroupConfigupgrade cluster --config-file …Blast radius outside the client
pkg/svc/provisioner/cluster/eks/{creation,update,provisioner}.go·pkg/svc/provider/aws/{provider,nodegroup_state,errors}.go·pkg/svc/clusterdiscovery/{cloud,availability}.go(both gate EKS discovery on the binary being onPATH) ·pkg/cli/cmd/cluster/info.go·pkg/apis/cluster/v1alpha1/errors.go·.github/workflows/system-test-eks.yaml(downloads an eksctl release) and.github/scripts/delete-eks-smoke-cluster.sh· seven pages underdocs/src, plusdocs/gen_docs_prose.goandAGENTS.md.*.eksctl.iokubeconfig context parsing (pkg/svc/detector/cluster/context.go,pkg/cli/setup/localregistry/resolve.go,vsce/src/ksail/contexts.ts) is not in scope for removal — those contexts exist on every cluster the CLI ever created and must keep parsing forever.Constraint: the eksctl declarative file stays authoritative
eks.yamlremains a valid eksctlClusterConfig(apiVersion: eksctl.io/v1alpha5). This is non-negotiable and the migration should improve compliance, not weaken it.Today
creation.goparses the file withyaml.UnmarshalStrictinto an untypedmap[string]anyplus a hand-rolled typed subset covering onlymanagedNodeGroups— everything else is passed through to the binary unvalidated by KSail. The binary is currently the only thing that checks the schema.github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5publishesClusterConfigalong withValidateClusterConfig,SetClusterConfigDefaults,SetNodeGroupDefaultsandSetManagedNodeGroupDefaults. Adopting those types means KSail validateseks.yamlwith the same code eksctl uses, so schema fidelity is guaranteed by construction rather than by re-implementation.pkg.go.dev reports that package's import graph as light — k8s apimachinery, aws-sdk-go-v2,
hashicorp/go-version,sigs.k8s.io/yaml,kris-nova/logger, and eksctl's ownutils/awsapi— with nopkg/ctl,pkg/actions, kops, cfssl, kubicorn or amazon-ec2-instance-selector. That is the treepkg/client/eksctl/doc.gocites as the reason not to embed, and it appears to apply topkg/actions/cluster, not to the API types. Confirm withgo mod graphbefore committing to it (#7117).Licensing
KSail ships under PolyForm Shield 1.0.0 — source-available with a noncompete clause, not OSI-approved. That makes inbound license hygiene a real constraint rather than a formality.
github.com/weaveworks/eksctl, still the module path) is reported by pkg.go.dev as Apache-2.0. Apache-2.0 is permissive with no copyleft, so linking it into a PolyForm-licensed binary is permitted.NOTICE, retain copyright/patent notices, and mark modified files if anything is vendored or forked.Migration plan
Each phase is independently shippable and leaves
mainreleasable. Phases 2–7 become sub-issues once #7117 has sized them.UpgradeClustershim. Add a CI license gate (go-licensesor equivalent) with an allowlist, so the dependency question is answered automatically from here on. No behaviour change.eksctl-<cluster>-*stack names and full CLI interoperability; or (b) provision natively withEKS/EC2/IAMSDK calls, matching howpkg/client/gkeandpkg/client/akswork. Output is an ADR plus follow-up issues — no PR.eks.yamlthrough upstreamv1alpha5types. The binary still does the work; user-visible effect is better error messages, earlier.get cluster/get nodegroupto the SDK. After this,ksail cluster info, cluster discovery and availability no longer need the binary at all.scale nodegroup→UpdateNodegroupConfig.spec.cluster.eks.experimentalNativeProvisioning, default off, per the repo's existingspec.cluster.eks.experimental*convention. The binary path stays the default.pkg/client/eksctlandErrEksctlBinaryMissing, drop the eksctl download from CI, update docs andAGENTS.md.What "non-breaking" means here
eks.yamlstays an eksctlClusterConfigv1alpha5 — no KSail-proprietary schema, ever.eksctl-*stack names,*.eksctl.iocontexts).Acceptance Criteria
NOTICEpropagated, notices retained.go mod graphconfirms the embedded eksctl packages do not pullpkg/ctl,pkg/actions, kops, cfssl, kubicorn or amazon-ec2-instance-selector — or [spike]: decide how KSail creates an EKS cluster without the eksctl binary #7117 records the measured cost and the decision taken.eksctl.Client.UpgradeClustershim is gone.docs/adr/records the create strategy and its interoperability trade-offs.eks.yamlis parsed and validated through upstreamv1alpha5types; a malformed config is rejected by KSail with a clear error before any AWS call.ksail cluster info, cluster discovery and availability work with noeksctlonPATH.ksail cluster create/delete/updatecomplete end to end with noeksctlonPATH, proven by a green live EKS smoke run.pkg/client/eksctlandErrEksctlBinaryMissingare deleted;*.eksctl.iocontext parsing is retained..github/workflows/system-test-eks.yamland.github/scripts/delete-eks-smoke-cluster.sh.AGENTS.mdno longer listeksctlas a prerequisite, and the support matrix reflects the native path.Out of scope
Completing the remaining KSail-managed component installers on EKS (#4328) and the EKS Auto Mode question. This epic changes how KSail talks to AWS, not what it installs afterwards.
References
eksctl.io/v1alpha5Go API