diff --git a/Makefile b/Makefile index 4a55a33e0..4bdc9115f 100644 --- a/Makefile +++ b/Makefile @@ -409,7 +409,7 @@ build-web: PLATFORMS ?= linux/$(ARCH) .PHONY: image-local image-local: - @echo "Building multi-arch images locally with tag $(REV) for platforms: $(PLATFORMS)" + @echo "Building images locally with tag $(REV) for platforms: $(PLATFORMS)" @command -v docker >/dev/null 2>&1 || { echo "docker not found. Please install Docker"; exit 1; } @docker buildx version >/dev/null 2>&1 || { echo "docker buildx not found. Please enable buildx in Docker"; exit 1; } @@ -417,25 +417,34 @@ image-local: @docker buildx create --name kube-bind-builder --use 2>/dev/null || docker buildx use kube-bind-builder 2>/dev/null || true @docker buildx inspect --bootstrap >/dev/null 2>&1 - @echo "Building konnector multi-arch image locally..." + @# Check if building for multiple platforms + @if [[ "$(PLATFORMS)" == *","* ]]; then \ + echo "Multi-platform build detected. Images will be pushed to registry instead of loaded locally."; \ + LOAD_FLAG="--push"; \ + else \ + echo "Single platform build. Images will be loaded to local Docker daemon."; \ + LOAD_FLAG="--load"; \ + fi && \ + \ + echo "Building konnector image..." && \ docker buildx build \ --platform $(PLATFORMS) \ --build-arg LDFLAGS="$(LDFLAGS)" \ -t $(IMAGE_REPO)/konnector:$(REV) \ -f Dockerfile.konnector \ - --load . - - @echo "Building backend multi-arch image locally..." + $$LOAD_FLAG . && \ + \ + echo "Building backend image..." && \ docker buildx build \ --platform $(PLATFORMS) \ --build-arg LDFLAGS="$(LDFLAGS)" \ -t $(IMAGE_REPO)/backend:$(REV) \ -f Dockerfile \ - --load . - - @echo "Successfully built multi-arch local images:" - @echo " $(IMAGE_REPO)/konnector:$(REV) ($(PLATFORMS))" - @echo " $(IMAGE_REPO)/backend:$(REV) ($(PLATFORMS))" + $$LOAD_FLAG . && \ + \ + echo "Successfully built images:" && \ + echo " $(IMAGE_REPO)/konnector:$(REV) ($(PLATFORMS))" && \ + echo " $(IMAGE_REPO)/backend:$(REV) ($(PLATFORMS))" # Kind cluster configuration KIND_CLUSTER ?= kube-bind diff --git a/cli/pkg/kubectl/bind-apiservice/cmd/cmd.go b/cli/pkg/kubectl/bind-apiservice/cmd/cmd.go index e6ec7ae37..0d0b59005 100644 --- a/cli/pkg/kubectl/bind-apiservice/cmd/cmd.go +++ b/cli/pkg/kubectl/bind-apiservice/cmd/cmd.go @@ -35,11 +35,8 @@ var ( # bind to a remote API service. Use kubectl bind to create the APIServiceExportRequest interactively. %[1]s apiservice --remote-kubeconfig file -f apiservice-export-request.yaml - # bind to a remote API service via a request manifest from a https URL. - %[1]s apiservice --remote-kubeconfig file https://some-url.com/apiservice-export-requests.yaml - - # bind to a API service directly without any remote agent or service provider. - %[1]s apiservice --remote-kubeconfig file -n remote-namespace resources.group/v1 + # bind to a remote API using template name + %[1]s apiservice --name my-api --template-name database-service ` ) diff --git a/cli/pkg/kubectl/bind-apiservice/plugin/bind.go b/cli/pkg/kubectl/bind-apiservice/plugin/bind.go index f57ded8ac..cf9200222 100644 --- a/cli/pkg/kubectl/bind-apiservice/plugin/bind.go +++ b/cli/pkg/kubectl/bind-apiservice/plugin/bind.go @@ -324,9 +324,9 @@ func (b *BindAPIServiceOptions) bindTemplate(ctx context.Context) (*bindTemplate return nil, err } if created { - fmt.Fprintf(b.Options.IOStreams.ErrOut, "Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) + fmt.Fprintf(b.Options.IOStreams.ErrOut, "🔒 Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) } else { - fmt.Fprintf(b.Options.IOStreams.ErrOut, "Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) + fmt.Fprintf(b.Options.IOStreams.ErrOut, "🔒 Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) } return &bindTemplateResult{ response: bindResponse, diff --git a/cli/pkg/kubectl/bind-apiservice/plugin/binder.go b/cli/pkg/kubectl/bind-apiservice/plugin/binder.go index fbf4799a1..9419c50ce 100644 --- a/cli/pkg/kubectl/bind-apiservice/plugin/binder.go +++ b/cli/pkg/kubectl/bind-apiservice/plugin/binder.go @@ -66,6 +66,17 @@ func NewBinder(config *rest.Config, opts *BinderOptions) *Binder { // https://github.com/kube-bind/kube-bind/issues/360 func (b *Binder) BindFromFile(ctx context.Context) ([]*kubebindv1alpha2.APIServiceBinding, error) { + // Generate the kubectl command that would be equivalent + remoteFlags := "" + if b.opts.RemoteKubeconfigFile != "" { + remoteFlags = fmt.Sprintf("--remote-kubeconfig %s", b.opts.RemoteKubeconfigFile) + } else if b.opts.RemoteKubeconfigNamespace != "" && b.opts.RemoteKubeconfigName != "" { + remoteFlags = fmt.Sprintf("--remote-kubeconfig-namespace %s --remote-kubeconfig-name %s", b.opts.RemoteKubeconfigNamespace, b.opts.RemoteKubeconfigName) + } + fmt.Fprintf(b.opts.IOStreams.ErrOut, "🚀 Executing: kubectl bind apiservice %s -f -\n", remoteFlags) + fmt.Fprintf(b.opts.IOStreams.ErrOut, "✨ Use \"-o yaml\" and \"--dry-run\" to get the APIServiceExportRequest.\n") + fmt.Fprintf(b.opts.IOStreams.ErrOut, " and pass it to \"kubectl bind apiservice\" directly. Great for automation.\n") + // Ensure client side namespace exists err := b.ensureClientSideNamespaceExists(ctx) if err != nil { @@ -99,9 +110,9 @@ func (b *Binder) BindFromFile(ctx context.Context) ([]*kubebindv1alpha2.APIServi } if created { - fmt.Fprintf(b.opts.IOStreams.ErrOut, "Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) + fmt.Fprintf(b.opts.IOStreams.ErrOut, "🔒 Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) } else { - fmt.Fprintf(b.opts.IOStreams.ErrOut, "Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) + fmt.Fprintf(b.opts.IOStreams.ErrOut, "🔒 Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) } if b.opts.DryRun { @@ -184,9 +195,9 @@ func (b *Binder) BindFromResponse(ctx context.Context, response *kubebindv1alpha } if created { - fmt.Fprintf(b.opts.IOStreams.ErrOut, "Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) + fmt.Fprintf(b.opts.IOStreams.ErrOut, "🔒 Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) } else { - fmt.Fprintf(b.opts.IOStreams.ErrOut, "Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) + fmt.Fprintf(b.opts.IOStreams.ErrOut, "🔒 Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) } if b.opts.DryRun { diff --git a/cli/pkg/kubectl/bind-apiservice/plugin/konnector.go b/cli/pkg/kubectl/bind-apiservice/plugin/konnector.go index f0f122c9f..77ffea05a 100644 --- a/cli/pkg/kubectl/bind-apiservice/plugin/konnector.go +++ b/cli/pkg/kubectl/bind-apiservice/plugin/konnector.go @@ -68,7 +68,7 @@ func (b *BindAPIServiceOptions) deployKonnector(ctx context.Context, config *res } if b.KonnectorImageOverride != "" { - fmt.Fprintf(b.Options.ErrOut, "Deploying konnector %s to namespace kube-bind with custom image %q.\n", bindVersion, b.KonnectorImageOverride) + fmt.Fprintf(b.Options.ErrOut, "🚀 Deploying konnector %s to namespace kube-bind with custom image %q.\n", bindVersion, b.KonnectorImageOverride) if err := konnector.Bootstrap(ctx, discoveryClient, dynamicClient, b.KonnectorImageOverride); err != nil { return err } @@ -103,7 +103,7 @@ func (b *BindAPIServiceOptions) deployKonnector(ctx context.Context, config *res } } } else { - fmt.Fprintf(b.Options.ErrOut, "Deploying konnector %s to namespace kube-bind.\n", bindVersion) + fmt.Fprintf(b.Options.ErrOut, "🚀 Deploying konnector %s to namespace kube-bind.\n", bindVersion) if err := konnector.Bootstrap(ctx, discoveryClient, dynamicClient, konnectorImage); err != nil { return err } diff --git a/cli/pkg/kubectl/bind-apiservice/plugin/secret.go b/cli/pkg/kubectl/bind-apiservice/plugin/secret.go index 937725b49..26645f77d 100644 --- a/cli/pkg/kubectl/bind-apiservice/plugin/secret.go +++ b/cli/pkg/kubectl/bind-apiservice/plugin/secret.go @@ -76,9 +76,9 @@ func (b *BindAPIServiceOptions) ensureKubeconfigSecretWithLogging(ctx context.Co if b.remoteKubeconfigFile != "" { if created { - fmt.Fprintf(b.Options.ErrOut, "Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) + fmt.Fprintf(b.Options.ErrOut, "🔒 Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) } else { - fmt.Fprintf(b.Options.ErrOut, "Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) + fmt.Fprintf(b.Options.ErrOut, "🔒 Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace) } } diff --git a/cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go b/cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go index 989bae851..b539c8b64 100644 --- a/cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go +++ b/cli/pkg/kubectl/bind-apiservice/plugin/servicebindings.go @@ -106,6 +106,6 @@ func (b *BindAPIServiceOptions) createAPIServiceBindings(ctx context.Context, co return nil, err } - fmt.Fprintf(b.Options.IOStreams.ErrOut, "Created APIServiceBinding %s for %d resources\n", bindingName, len(request.Spec.Resources)) + fmt.Fprintf(b.Options.IOStreams.ErrOut, "✅ Created APIServiceBinding %s for %d resources\n", bindingName, len(request.Spec.Resources)) return []*kubebindv1alpha2.APIServiceBinding{created}, nil } diff --git a/cli/pkg/kubectl/bind-collections/cmd/cmd.go b/cli/pkg/kubectl/bind-collections/cmd/cmd.go index bd73d26d6..ab90581a7 100644 --- a/cli/pkg/kubectl/bind-collections/cmd/cmd.go +++ b/cli/pkg/kubectl/bind-collections/cmd/cmd.go @@ -32,14 +32,12 @@ var ( # List collections from currently authenticated server %[1]s collections - # List collections from specific server - %[1]s collections https://mangodb.com - # List collections using --server flag to override current server %[1]s collections --server https://mangodb.com - # List collections with JSON output + # List collections with JSON/YAML output %[1]s collections -o json + %[1]s collections -o yaml ` ) diff --git a/cli/pkg/kubectl/bind-login/plugin/login.go b/cli/pkg/kubectl/bind-login/plugin/login.go index 582e1dd3b..289b14ccc 100644 --- a/cli/pkg/kubectl/bind-login/plugin/login.go +++ b/cli/pkg/kubectl/bind-login/plugin/login.go @@ -209,10 +209,10 @@ func (o *LoginOptions) Run(ctx context.Context, authURLCh chan<- string) error { } if token.Cluster != "" { - fmt.Fprintf(o.Streams.ErrOut, "Successfully authenticated to %s (cluster: %s)\n", serverHost.Host, token.Cluster) - fmt.Fprintf(o.Streams.ErrOut, " Server key: %s\n", fmt.Sprintf("%s@%s", serverURL, token.Cluster)) + fmt.Fprintf(o.Streams.ErrOut, "🔑 Successfully authenticated to %s (cluster: %s)\n", serverHost.Host, token.Cluster) + fmt.Fprintf(o.Streams.ErrOut, " Server key: %s\n", fmt.Sprintf("%s@%s", serverURL, token.Cluster)) } else { - fmt.Fprintf(o.Streams.ErrOut, "Successfully authenticated to %s\n", serverHost.Host) + fmt.Fprintf(o.Streams.ErrOut, "🔑 Successfully authenticated to %s\n", serverHost.Host) } if o.ShowToken { diff --git a/cli/pkg/kubectl/bind-templates/cmd/cmd.go b/cli/pkg/kubectl/bind-templates/cmd/cmd.go index 52bc314ad..3fab4188b 100644 --- a/cli/pkg/kubectl/bind-templates/cmd/cmd.go +++ b/cli/pkg/kubectl/bind-templates/cmd/cmd.go @@ -33,13 +33,14 @@ var ( %[1]s templates # List templates from specific server - %[1]s templates https://mangodb.com + %[1]s templates # List templates using --server flag to override current server %[1]s templates --server https://mangodb.com - # List templates with JSON output + # List templates with JSON/YAML output %[1]s templates -o json + %[1]s templates -o yaml ` ) diff --git a/cli/pkg/kubectl/bind/cmd/cmd.go b/cli/pkg/kubectl/bind/cmd/cmd.go index 46e9cdd39..a8553efa2 100644 --- a/cli/pkg/kubectl/bind/cmd/cmd.go +++ b/cli/pkg/kubectl/bind/cmd/cmd.go @@ -20,7 +20,6 @@ import ( "fmt" "strings" - "github.com/fatih/color" "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" logsv1 "k8s.io/component-base/logs/api/v1" @@ -34,23 +33,19 @@ import ( var ( BindExampleUses = ` - # Open kube-bind UI for current server context - %[1]s bind + # %[1]s bind login --server https://my-kube-bind-server.com - # Open kube-bind UI for specific server - %[1]s bind https://mangodb.com + # Open kube-bind UI for current server context + %[1]s bind # List available templates (CLI mode) - %[1]s bind --dry-run + %[1]s bind templates # Bind specific template (CLI mode) - %[1]s bind --template my-app - - # Bind template with server override - %[1]s bind https://mangodb.com --template my-app + %[1]s bind apiservice --name my-api --template-name database-service # View template details without binding - %[1]s bind --template my-app --dry-run + %[1]s bind apiservice --name my-api --template-name database-service --dry-run ` ) @@ -64,9 +59,8 @@ func New(streams genericclioptions.IOStreams) (*cobra.Command, error) { a web UI or command-line interface. By default, 'kubectl bind' opens the kube-bind web UI in your browser. - Use the --template flag to bind specific templates via CLI. - For more information, see: https://kube-bind.io + For more information, see: https://docs.kube-bind.io `), Example: fmt.Sprintf(BindExampleUses, "kubectl"), SilenceUsage: true, @@ -89,9 +83,6 @@ func New(streams genericclioptions.IOStreams) (*cobra.Command, error) { return err } - yellow := color.New(color.BgRed, color.FgBlack).SprintFunc() - fmt.Fprintf(streams.ErrOut, "%s\n\n", yellow("DISCLAIMER: This is a prototype. It will change in incompatible ways at any time.")) - if err := opts.Complete(args); err != nil { return err } diff --git a/contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml b/contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml index 0b7b1f367..6806b1fe5 100644 --- a/contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml +++ b/contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml @@ -64,7 +64,7 @@ spec: crd: {} - group: kube-bind.io name: apiserviceexporttemplates - schema: v251029-fadb9ed.apiserviceexporttemplates.kube-bind.io + schema: v251106-640871f.apiserviceexporttemplates.kube-bind.io storage: crd: {} - group: kube-bind.io @@ -79,7 +79,7 @@ spec: crd: {} - group: kube-bind.io name: boundschemas - schema: v250918-f26732b.boundschemas.kube-bind.io + schema: v251106-640871f.boundschemas.kube-bind.io storage: crd: {} - group: kube-bind.io @@ -89,7 +89,7 @@ spec: crd: {} - group: kube-bind.io name: collections - schema: v251022-ca928ec.collections.kube-bind.io + schema: v251106-640871f.collections.kube-bind.io storage: crd: {} status: {} diff --git a/contrib/kcp/deploy/resources/apiresourceschema-apiserviceexporttemplates.kube-bind.io.yaml b/contrib/kcp/deploy/resources/apiresourceschema-apiserviceexporttemplates.kube-bind.io.yaml index 2ef398575..fa44d4a4d 100644 --- a/contrib/kcp/deploy/resources/apiresourceschema-apiserviceexporttemplates.kube-bind.io.yaml +++ b/contrib/kcp/deploy/resources/apiresourceschema-apiserviceexporttemplates.kube-bind.io.yaml @@ -2,7 +2,7 @@ apiVersion: apis.kcp.io/v1alpha1 kind: APIResourceSchema metadata: creationTimestamp: null - name: v251029-fadb9ed.apiserviceexporttemplates.kube-bind.io + name: v251106-640871f.apiserviceexporttemplates.kube-bind.io spec: group: kube-bind.io names: @@ -26,8 +26,10 @@ spec: type: date name: v1alpha2 schema: - description: APIServiceExportTemplate groups multiple CRDs with related resources - (permissionClaims) as a Service definition. + description: |- + APIServiceExportTemplate groups multiple CRDs with related resources (permissionClaims) as a Service definition. + It is used by a web UI or CLI to allow users to select a set of resources to export from provider cluster to consumer cluster. + This object is considered a static asset on the provider side and is not expected to change frequently. properties: apiVersion: description: |- diff --git a/contrib/kcp/deploy/resources/apiresourceschema-boundschemas.kube-bind.io.yaml b/contrib/kcp/deploy/resources/apiresourceschema-boundschemas.kube-bind.io.yaml index e0afec0b6..a764341d1 100644 --- a/contrib/kcp/deploy/resources/apiresourceschema-boundschemas.kube-bind.io.yaml +++ b/contrib/kcp/deploy/resources/apiresourceschema-boundschemas.kube-bind.io.yaml @@ -2,7 +2,7 @@ apiVersion: apis.kcp.io/v1alpha1 kind: APIResourceSchema metadata: creationTimestamp: null - name: v250918-f26732b.boundschemas.kube-bind.io + name: v251106-640871f.boundschemas.kube-bind.io spec: conversion: strategy: None @@ -24,7 +24,9 @@ spec: type: date name: v1alpha2 schema: - description: BoundSchema + description: |- + BoundSchema defines the schema of a bound API resource. It is created on the provider side to track + CRD status on the consumer side by reflecting the CRD spec and status conditions. properties: apiVersion: description: |- diff --git a/contrib/kcp/deploy/resources/apiresourceschema-collections.kube-bind.io.yaml b/contrib/kcp/deploy/resources/apiresourceschema-collections.kube-bind.io.yaml index 8c4127e16..8e051195d 100644 --- a/contrib/kcp/deploy/resources/apiresourceschema-collections.kube-bind.io.yaml +++ b/contrib/kcp/deploy/resources/apiresourceschema-collections.kube-bind.io.yaml @@ -2,7 +2,7 @@ apiVersion: apis.kcp.io/v1alpha1 kind: APIResourceSchema metadata: creationTimestamp: null - name: v251022-ca928ec.collections.kube-bind.io + name: v251106-640871f.collections.kube-bind.io spec: group: kube-bind.io names: @@ -26,8 +26,9 @@ spec: type: date name: v1alpha2 schema: - description: Collection groups multiple APIServiceExportTemplates into a logical - group. This functions as a folder in the UI. + description: |- + Collection groups multiple APIServiceExportTemplates into a logical group. This functions as a grouping mechanism + in UIs or CLIs to allow users to select a set of resources to export from provider cluster to consumer cluster. properties: apiVersion: description: |- diff --git a/deploy/charts/backend/crds/kube-bind.io_apiserviceexporttemplates.yaml b/deploy/charts/backend/crds/kube-bind.io_apiserviceexporttemplates.yaml index f7e322217..aa078c00e 100644 --- a/deploy/charts/backend/crds/kube-bind.io_apiserviceexporttemplates.yaml +++ b/deploy/charts/backend/crds/kube-bind.io_apiserviceexporttemplates.yaml @@ -29,8 +29,10 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: APIServiceExportTemplate groups multiple CRDs with related resources - (permissionClaims) as a Service definition. + description: |- + APIServiceExportTemplate groups multiple CRDs with related resources (permissionClaims) as a Service definition. + It is used by a web UI or CLI to allow users to select a set of resources to export from provider cluster to consumer cluster. + This object is considered a static asset on the provider side and is not expected to change frequently. properties: apiVersion: description: |- diff --git a/deploy/charts/backend/crds/kube-bind.io_boundschemas.yaml b/deploy/charts/backend/crds/kube-bind.io_boundschemas.yaml index fe67f2837..80e87a042 100644 --- a/deploy/charts/backend/crds/kube-bind.io_boundschemas.yaml +++ b/deploy/charts/backend/crds/kube-bind.io_boundschemas.yaml @@ -25,7 +25,9 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: BoundSchema + description: |- + BoundSchema defines the schema of a bound API resource. It is created on the provider side to track + CRD status on the consumer side by reflecting the CRD spec and status conditions. properties: apiVersion: description: |- diff --git a/deploy/charts/backend/crds/kube-bind.io_collections.yaml b/deploy/charts/backend/crds/kube-bind.io_collections.yaml index b95bc0f89..1b262685d 100644 --- a/deploy/charts/backend/crds/kube-bind.io_collections.yaml +++ b/deploy/charts/backend/crds/kube-bind.io_collections.yaml @@ -29,8 +29,9 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: Collection groups multiple APIServiceExportTemplates into a logical - group. This functions as a folder in the UI. + description: |- + Collection groups multiple APIServiceExportTemplates into a logical group. This functions as a grouping mechanism + in UIs or CLIs to allow users to select a set of resources to export from provider cluster to consumer cluster. properties: apiVersion: description: |- diff --git a/deploy/crd/kube-bind.io_apiserviceexporttemplates.yaml b/deploy/crd/kube-bind.io_apiserviceexporttemplates.yaml index f7e322217..aa078c00e 100644 --- a/deploy/crd/kube-bind.io_apiserviceexporttemplates.yaml +++ b/deploy/crd/kube-bind.io_apiserviceexporttemplates.yaml @@ -29,8 +29,10 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: APIServiceExportTemplate groups multiple CRDs with related resources - (permissionClaims) as a Service definition. + description: |- + APIServiceExportTemplate groups multiple CRDs with related resources (permissionClaims) as a Service definition. + It is used by a web UI or CLI to allow users to select a set of resources to export from provider cluster to consumer cluster. + This object is considered a static asset on the provider side and is not expected to change frequently. properties: apiVersion: description: |- diff --git a/deploy/crd/kube-bind.io_boundschemas.yaml b/deploy/crd/kube-bind.io_boundschemas.yaml index 41980ee1e..42399192d 100644 --- a/deploy/crd/kube-bind.io_boundschemas.yaml +++ b/deploy/crd/kube-bind.io_boundschemas.yaml @@ -26,7 +26,9 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: BoundSchema + description: |- + BoundSchema defines the schema of a bound API resource. It is created on the provider side to track + CRD status on the consumer side by reflecting the CRD spec and status conditions. properties: apiVersion: description: |- diff --git a/deploy/crd/kube-bind.io_collections.yaml b/deploy/crd/kube-bind.io_collections.yaml index b95bc0f89..1b262685d 100644 --- a/deploy/crd/kube-bind.io_collections.yaml +++ b/deploy/crd/kube-bind.io_collections.yaml @@ -29,8 +29,9 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: Collection groups multiple APIServiceExportTemplates into a logical - group. This functions as a folder in the UI. + description: |- + Collection groups multiple APIServiceExportTemplates into a logical group. This functions as a grouping mechanism + in UIs or CLIs to allow users to select a set of resources to export from provider cluster to consumer cluster. properties: apiVersion: description: |- diff --git a/docs/content/.pages b/docs/content/.pages index 38cfd704f..6a12b5a3b 100644 --- a/docs/content/.pages +++ b/docs/content/.pages @@ -2,7 +2,6 @@ nav: - Home: - index.md - Setup: setup - - Usage: usage - Contributing: contributing - Developers: developers - - Reference: reference + - API References: reference diff --git a/docs/content/contributing/commit-tag.png b/docs/content/contributing/commit-tag.png deleted file mode 100644 index 657c3b300..000000000 Binary files a/docs/content/contributing/commit-tag.png and /dev/null differ diff --git a/docs/content/contributing/github_summary.png b/docs/content/contributing/github_summary.png deleted file mode 100644 index 1c7b8417b..000000000 Binary files a/docs/content/contributing/github_summary.png and /dev/null differ diff --git a/docs/content/contributing/index.md b/docs/content/contributing/index.md index a996e3b3f..f2cca590c 100644 --- a/docs/content/contributing/index.md +++ b/docs/content/contributing/index.md @@ -3,7 +3,7 @@ kube-bind is [Apache 2.0 licensed](https://github.com/kube-bind/kube-bind/tree/main/LICENSE) and we accept contributions via GitHub pull requests. -Please read the following guide if you're interested in contributing to kcp. +Please read the following guide if you're interested in contributing to kube-bind. ## Certificate of Origin @@ -20,18 +20,20 @@ contribution. See the [DCO](https://github.com/kube-bind/kube-bind/tree/main/DCO 2. [Install Go](https://golang.org/doc/install) (currently 1.22). 3. Install [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl). +More on the development environment setup can be found in the [developer guide](../developers/dev-environments.md). + ## Finding Areas to Contribute Starting to participate in a new project can sometimes be overwhelming, and you may not know where to begin. Fortunately, we are here to help! We track all of our tasks here in GitHub, and we label our issues to categorize them. Here are a couple of handy links to check out: -* [Good first issue](https://github.com/kcp-dev/kcp/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) issues -* [Help wanted](https://github.com/kcp-dev/kcp/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues +* [Good first issue](https://github.com/kube-bind/kube-bind/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) issues +* [Help wanted](https://github.com/kube-bind/kube-bind/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) issues You're certainly not limited to only these kinds of issues, though! If you're comfortable, please feel free to try working on anything that is open. We do use the assignee feature in GitHub for issues. If you find an unassigned issue, comment asking if you can be assigned, and ideally wait for a maintainer to respond. If you find an assigned issue and you want to work on it or help out, please reach out to the assignee first. -Sometimes you might get an amazing idea and start working on a huge amount of code. We love and encourage excitement like this, but we do ask that before you embarking on a giant pull request, please reach out to the community first for an initial discussion. You could [file an issue](https://github.com/kube-bind/kube-bind/issues/new/choose), send a discussion to our [mailing list](https://groups.google.com/g/kube-bind-dev), and/or join one of our [community meetings](https://docs.google.com/document/d/1PrEhbmq1WfxFv1fTikDBZzXEIJkUWVHdqDFxaY1Ply4). +Sometimes you might get an amazing idea and start working on a huge amount of code. We love and encourage excitement like this, but we do ask that before you embark on a giant pull request, please reach out to the community first for an initial discussion. You could [file an issue](https://github.com/kube-bind/kube-bind/issues/new/choose), send a discussion to our [mailing list](https://groups.google.com/g/kube-bind-dev), and/or join one of our [community meetings](https://docs.google.com/document/d/1qztpKOmdZu5iWq_4N9n3AZpcAPuPhBiGNbje5GPg0iM). Finally, we welcome and value all types of contributions, beyond "just code"! Other types include triaging bugs, tracking down and fixing flaky tests, improving our documentation, helping answer community questions, proposing and reviewing designs, etc. @@ -51,7 +53,7 @@ that might not be obvious to the contributor. ### Approvers Approvers are responsible for sign-off on the acceptance of the contribution. In essence, approval indicates that the -change is desired and good for the project, aligns with code, api, and system conventions, and appears to follow all required +change is desired and good for the project, aligns with code, API, and system conventions, and appears to follow all required process including adequate testing, documentation, follow ups, or notifications to other areas who might be interested or affected by the change. diff --git a/docs/content/contributing/promecieus.png b/docs/content/contributing/promecieus.png deleted file mode 100644 index 501c33245..000000000 Binary files a/docs/content/contributing/promecieus.png and /dev/null differ diff --git a/docs/content/contributing/prow_link.png b/docs/content/contributing/prow_link.png deleted file mode 100644 index c507bff6d..000000000 Binary files a/docs/content/contributing/prow_link.png and /dev/null differ diff --git a/docs/content/developers/.pages b/docs/content/developers/.pages index 1d588e8f9..a549ca52d 100644 --- a/docs/content/developers/.pages +++ b/docs/content/developers/.pages @@ -1,4 +1,6 @@ nav: - index.md + - Development Environment: dev-environments.md - Backend: backend - Konnector: konnector + - Publishing a release: publishing-a-release.md \ No newline at end of file diff --git a/docs/content/developers/dev-environments.md b/docs/content/developers/dev-environments.md new file mode 100644 index 000000000..36d105e8f --- /dev/null +++ b/docs/content/developers/dev-environments.md @@ -0,0 +1,543 @@ +--- +description: > + How to setup a development environment for contributing to kube-bind. +title: Developer Guide +--- + +# Development Environment + +!!! note + There are multiple ways to set up a development environment for kube-bind. This guide outlines one of the common approaches using `kind` and `kcp`. You can adapt these instructions based on your preferences and existing setups. + +Due to the fact that kube-bind is by nature a multi-cluster system, for development purposes it's recommended to have multiple clusters running or use kcp to simulate multiple clusters. Below are instructions for both approaches. + +All the instructions assume you have already cloned the kube-bind repository and have Go installed. + +=== "kcp" + + kcp requires initial setup to be run before it can be used. + This includes setting up workspace/provider and setting up all the APIResourceSchemas and APIExports. + + It has its own Go module to avoid kcp dependencies in the main kube-bind module. + + This is not required if you are doing deeper integration, and controlling the setup with your own scripts. + + It's good to have the kcp CLI installed to help with workspace management: + + ```bash + kubectl krew index add kcp-dev https://github.com/kcp-dev/krew-index.git + kubectl krew install kcp-dev/kcp + kubectl krew install kcp-dev/ws + kubectl krew install kcp-dev/create-workspace + ``` + + # How to run + + ## Preparation + + 1. Start dex + + ```bash + make run-dex + ``` + + 2. Start kcp + + ```bash + make run-kcp + ``` + + ## Backend + + 3. Bootstrap kcp. This is a dedicated step to set up kcp with required workspaces and APIExports for kube-bind: + ```bash + cp .kcp/admin.kubeconfig .kcp/backend.kubeconfig + export KUBECONFIG=.kcp/backend.kubeconfig + ./bin/kcp-init --kcp-kubeconfig $KUBECONFIG + ``` + 4. Run the backend: + ``` + k ws use :root:kube-bind + + ./bin/backend \ + --multicluster-runtime-provider kcp \ + --server-url=$(kubectl get apiexportendpointslice kube-bind.io -o jsonpath="{.status.endpoints[0].url}") \ + --oidc-issuer-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 \ + --oidc-issuer-client-id=kube-bind \ + --oidc-issuer-url=http://127.0.0.1:5556/dex \ + --oidc-callback-url=http://127.0.0.1:8080/api/callback \ + --pretty-name="BigCorp.com" \ + --namespace-prefix="kube-bind-" \ + --cookie-signing-key=bGMHz7SR9XcI9JdDB68VmjQErrjbrAR9JdVqjAOKHzE= \ + --cookie-encryption-key=wadqi4u+w0bqnSrVFtM38Pz2ykYVIeeadhzT34XlC1Y= \ + --schema-source apiresourceschemas \ + --consumer-scope=cluster + ``` + + This process will keep running, so open a new terminal. + + ## Provider + + 5. Copy the kubeconfig to the provider and create provider workspace: + ```bash + cp .kcp/admin.kubeconfig .kcp/provider.kubeconfig + export KUBECONFIG=.kcp/provider.kubeconfig + k ws use :root + kubectl create-workspace provider --enter + ``` + + 6. Bind the APIExport to the provider workspace + ```bash + kubectl kcp bind apiexport root:kube-bind:kube-bind.io \ + --accept-permission-claim clusterrolebindings.rbac.authorization.k8s.io \ + --accept-permission-claim clusterroles.rbac.authorization.k8s.io \ + --accept-permission-claim customresourcedefinitions.apiextensions.k8s.io \ + --accept-permission-claim serviceaccounts.core \ + --accept-permission-claim configmaps.core \ + --accept-permission-claim secrets.core \ + --accept-permission-claim namespaces.core \ + --accept-permission-claim roles.rbac.authorization.k8s.io \ + --accept-permission-claim rolebindings.rbac.authorization.k8s.io \ + --accept-permission-claim apiresourceschemas.apis.kcp.io + ``` + + 7. Create CRD in provider: + ```bash + kubectl apply -f contrib/kcp/deploy/examples/apiexport.yaml + kubectl apply -f contrib/kcp/deploy/examples/apiresourceschema-cowboys.yaml + kubectl apply -f contrib/kcp/deploy/examples/apiresourceschema-sheriffs.yaml + kubectl kcp bind apiexport root:provider:cowboys-stable + + kubectl apply -f contrib/kcp/deploy/examples/template-cowboys.yaml + kubectl apply -f contrib/kcp/deploy/examples/template-sheriffs.yaml + kubectl apply -f contrib/kcp/deploy/examples/collection-wildwest.yaml + ``` + + 8. Get LogicalCluster: + + ```bash + kubectl get logicalcluster + # NAME PHASE URL AGE + # cluster Ready https://192.168.2.166:6443/clusters/1y7tqtsucxaekmqu + ``` + + ## Consumer + + 9. Now we gonna initiate consumer: + ```bash + cp .kcp/admin.kubeconfig .kcp/consumer.kubeconfig + export KUBECONFIG=.kcp/consumer.kubeconfig + kubectl ws use :root + kubectl ws create consumer --enter + ``` + + 10. Bind the thing: + + ```bash + ./bin/kubectl-bind login http://127.0.0.1:8080 --cluster + ./bin/kubectl-bind --dry-run -o yaml > apiserviceexport.yaml + + # Extract secret for binding process. Note that secret name is not the same as output from command above. Check secret + # name by running `kubectl get secret -n kube-bind` + kubectl get secrets -n kube-bind -o jsonpath='{.items[0].data.kubeconfig}' | base64 -d > remote.kubeconfig + + namespace=$(yq '.contexts[0].context.namespace' remote.kubeconfig) + + ./bin/kubectl-bind apiservice -v 6 --remote-kubeconfig remote.kubeconfig -f apiserviceexport.yaml --skip-konnector --remote-namespace "$namespace" + ``` + + This will keep running, so switch to a new terminal. + + ### Consumer Konnector + + Start konnector: + + ```bash + ./bin/konnector --lease-namespace default --kubeconfig .kcp/consumer.kubeconfig + ``` + + Optionally add second consumer to test + + ```bash + cp .kcp/admin.kubeconfig .kcp/consumer2.kubeconfig + export KUBECONFIG=.kcp/consumer2.kubeconfig + kubectl ws use :root + kubectl ws create consumer2 --enter + + ./bin/kubectl-bind http://127.0.0.1:8080/clusters/2vgrh380y0cq38du/exports --dry-run -o yaml > apiserviceexport2.yaml + + kubectl get secrets -n kube-bind -o jsonpath='{.items[0].data.kubeconfig}' | base64 -d > remote2.kubeconfig + + ./bin/kubectl-bind apiservice -v 6 --remote-kubeconfig remote2.kubeconfig -f apiserviceexport2.yaml --skip-konnector --remote-namespace "$(yq '.contexts[0].context.namespace' remote2.kubeconfig)" + + ./bin/konnector --lease-namespace default --kubeconfig .kcp/consumer2.kubeconfig --server-address :8091 + ``` + + This will keep running, so switch to a new terminal. + + ## Testing + + Create objects: + ``` + export KUBECONFIG=.kcp/consumer.kubeconfig + kubectl apply -f contrib/kcp/deploy/examples/cowboy.yaml + kubectl apply -f contrib/kcp/deploy/examples/sheriff.yaml + ``` + + ## Debug + + ```bash + + cp .kcp/admin.kubeconfig .kcp/debug.kubeconfig + export KUBECONFIG=.kcp/debug.kubeconfig + k ws use :root:kube-bind + + k -s "$(kubectl get apiexportendpointslice kube-bind.io -o jsonpath='{.status.endpoints[0].url}')/clusters/*" api-resources + + k -s "$(kubectl get apiexportendpointslice kube-bind.io -o jsonpath='{.status.endpoints[0].url}')/clusters/*" get crd + + namespace=$(yq '.contexts[0].context.namespace' remote.kubeconfig) + + # some claimed objects + + kubectl create cm provider -n "$namespace-default" + kubectl label cm provider app=wildwest -n "$namespace-default" + + kubectl create cm consumer -n default + kubectl label cm consumer app=wildwest -n default + + kubectl create secret generic provider-secret + kubectl label secret provider-secret app=wildwest + + kubectl create namespace bob + kubectl create secret generic wildwest-secrets1 -n bob + kubectl label secret wildwest-secrets1 app=wildwest -n bob + ``` + +=== "Kind" + + This guide will walk you through setting up kube-bind between two Kubernetes clusters, where + + * **Backend cluster**: + * Deploys dex, cert-manager and kube-bind/backend + * Provides kube-bind compatible backend for MangoDB resources + + * **App cluster**: + * Provides an application consuming MangoDBs + + This guide works best on Linux. macOS and Windows users may need to adjust some commands accordingly. + + ## Pre-requisites + + To start, you'll need the following tools available in your system or a VM: + + * [`kind`](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) + * [`kubectl`](https://kubernetes.io/docs/tasks/tools/) + * [`kubectl-bind`](https://github.com/kube-bind/kube-bind/releases/latest) (a kubectl plugin) + * [`helm`](https://helm.sh/docs/intro/quickstart/) + * [`jq`](https://jqlang.github.io/jq/download/) + + To install `kubectl-bind` plugin, please download the archive for your platform from the link above, extract it, and place the `kubectl-bind` executable in your system's `$PATH`. + + > Tip: In case of encountering `Too many open files` error when deploying the Kind clusters, run following commands: + > + > ```sh + > sudo sysctl fs.inotify.max_user_watches=524288 + > sudo sysctl fs.inotify.max_user_instances=512 + > ``` + > + > See the [kind documentation](https://kind.sigs.k8s.io/docs/user/known-issues/#pod-errors-due-to-too-many-open-files) for more details. + + ## Provider cluster + + The provider cluster we'll prepare in this section will provide a kube-bind compatible backend that will provide a controller for a demo resource "MangoDB" we'll consume in another cluster later. + + > What is MangoDB? It is just an example CRD to demonstrate kube-bind's capabilities and testing, without any workloads. See its definition in [/test/e2e/bind/fixtures/provider/crd-mangodb.yaml](/test/e2e/bind/fixtures/provider/crd-mangodb.yaml). + + ### Step one: create the Backend cluster + + First, stash the host's external IP in a variable as we're going to use it often: + + ```sh + # Linux + export BACKEND_HOST_IP="$(hostname -i | cut -d' ' -f1)" + ``` + + Create a Kind cluster named "backend": + + ```sh + cat << EOF_BackendClusterDefinition | kind create cluster --config=- + apiVersion: kind.x-k8s.io/v1alpha4 + kind: Cluster + name: backend + networking: + apiServerAddress: ${BACKEND_HOST_IP} + nodes: + - role: control-plane + extraPortMappings: + # MangoDB export endpoint + - containerPort: 30080 + hostPort: 8080 + protocol: TCP + # dex endpoint + - containerPort: 30556 + hostPort: 5556 + protocol: TCP + EOF_BackendClusterDefinition + ``` + + > Note: the port mappings will become clear later on, but in general this setup is solely specific to how Kind exposes ports of its nodes on the host. Specifically, we're exposing ports from containers through NodePort services on Kind's nodes, and to make these ports available on the host we need to map them to host's ports through `extraPortMappings`. + + ### Step two: deploy an identity provider + + kube-bind relies on OAuth2 for securely authenticating consumer and producer clusters. There are many ways to handle that in Kubernetes, for example with [dex IDP](https://github.com/dexidp/dex). It depends on cert-manager, which we'll deploy first: + + ```sh + helm repo add jetstack https://charts.jetstack.io + helm install \ + --create-namespace \ + --namespace pki \ + --version v1.16.2 \ + --set crds.enabled=true \ + cert-manager jetstack/cert-manager + ``` + + And now let's deploy dex: + + ```sh + helm repo add dex https://charts.dexidp.io + cat << EOF_DEXDeploymentConfig | + config: + staticClients: + - id: kube-bind + redirectURIs: + - 'http://${BACKEND_HOST_IP}:8080/api/callback' + name: 'Kube Bind' + secret: ZXhhbXBsZS1hcHAtc2VjcmV0 + + issuer: http://${BACKEND_HOST_IP}:5556/dex + + storage: + type: kubernetes + config: + inCluster: true + + web: + http: 127.0.0.1:5556 + + telemetry: + http: 127.0.0.1:5558 + + grpc: + addr: 127.0.0.1:5557 + + connectors: + - type: mockCallback + id: mock + name: Example + + enablePasswordDB: true + staticPasswords: + - email: "admin@example.com" + hash: "\$2a\$10\$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" + username: "admin" + userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" + EOF_DEXDeploymentConfig + helm install \ + --create-namespace \ + --namespace idp \ + --set service.type=NodePort \ + --set service.ports.http.nodePort=30556 \ + dex dex/dex \ + -f - + ``` + + ### Step three: deploy the MangoDB kube-bind backend + + Now we'll deploy a kube-bind-compatible backend for MangoDB. Let's start with kube-bind CRDs: + + ```sh + kubectl apply -f deploy/crd + ``` + + And now CRDs for MangoDB and related resources to be provided by the backend: + ```sh + kubectl apply -f deploy/examples/crd-mangodb.yaml + kubectl apply -f deploy/examples/crd-foo.yaml + kubectl apply -f deploy/examples/template-mangodb.yaml + kubectl apply -f deploy/examples/template-foo.yaml + kubectl apply -f deploy/examples/collection.yaml + ``` + + To set up the MangoDB backend we'll need: + * ServiceAccount and ClusterRoleBinding for kube-bind's user, + * Deployment that runs the MangoDB backend + * Service that exposes the backend's address + + ```sh + kubectl create namespace backend + # This is the address that will be used when generating kubeconfigs the App cluster, + # and so we need to be able to reach it from outside. + export BACKEND_KUBE_API_EXTERNAL_ADDRESS="$(kubectl config view --minify -o json | jq '.clusters[0].cluster.server' -r)" + # For demo example let's just bind "cluster-admin" ClusterRole to backend's "default" ServiceAccount. + kubectl create clusterrolebinding backend-admin --clusterrole cluster-admin --serviceaccount backend:default + # Create a new Deployment for the MangoDB backend. + kubectl --namespace backend \ + create deployment mangodb \ + --image ghcr.io/kube-bind/backend:main \ + --port 8080 \ + -- /bin/backend \ + --listen-address 0.0.0.0:8080 \ + --external-address "${BACKEND_KUBE_API_EXTERNAL_ADDRESS}" \ + --oidc-issuer-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 \ + --oidc-issuer-client-id=kube-bind \ + --oidc-issuer-url=http://${BACKEND_HOST_IP}:5556/dex \ + --oidc-callback-url=http://${BACKEND_HOST_IP}:8080/api/callback \ + --pretty-name="BigCorp.com" \ + --namespace-prefix="kube-bind-" \ + --cookie-signing-key=bGMHz7SR9XcI9JdDB68VmjQErrjbrAR9JdVqjAOKHzE= \ + --cookie-encryption-key=wadqi4u+w0bqnSrVFtM38Pz2ykYVIeeadhzT34XlC1Y= + # Expose mangodb's container port 8080 as a NodePort at 30080. We've already configured + # Kind to expose 30800 at host's 8080. + kubectl --namespace backend \ + create service nodeport mangodb \ + --tcp 8080 \ + --node-port 30080 + ``` + + And that's really all there's to it. After that, you should see a kubectl output similar to this: + + ```shell + $ kubectl --namespace backend get all + NAME READY STATUS RESTARTS AGE + pod/mangodb-6ff44cbbf-x7cjm 1/1 Running 0 100s + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + service/mangodb NodePort 10.96.10.212 8080:30080/TCP 100s + + NAME READY UP-TO-DATE AVAILABLE AGE + deployment.apps/mangodb 1/1 1 1 100s + + NAME DESIRED CURRENT READY AGE + replicaset.apps/mangodb-6ff44cbbf 1 1 1 100s + ``` + + ## Consumer App cluster + + The App cluster will consume MangoDB CRs provided by the Backend. + + ### Step one: create the App cluster + + Again, let's start by stashing the host's external IP in a variable as we're going to use it often (possibly the same one as for the Backend cluster): + + ```sh + export APP_HOST_IP="$(hostname -i | cut -d' ' -f1)" + ``` + + Create a Kind cluster named "app": + + ```sh + cat << EOF_AppClusterDefinition | kind create cluster --config=- + apiVersion: kind.x-k8s.io/v1alpha4 + kind: Cluster + name: app + networking: + apiServerAddress: ${APP_HOST_IP} + EOF_AppClusterDefinition + ``` + + ### Binding MangoDB backend + + Now we'll bring in MangoDB CRDs from the Backend cluster (you can run `kubectl get crds` to see there are none yet): + + ```sh + kubectl bind login http://${BACKEND_HOST_IP}:8080 + kubectl bind + 🌐 Opening kube-bind UI in your browser... + http://127.0.0.1:8080?cluster_id=7yw1thtocnvdhf74&redirect_url=http%3A%2F%2F127.0.0.1%3A63385%2Fcallback&session_id=UHKJVXR3VGT73VUUVVV7E7ERB5 + + Waiting for binding completion from UI... + (Press Ctrl+C to cancel) + ``` + + The client is now waiting for you to visit the address similar to the one displayed in the output above. After completing the steps to create an OAuth2 token, it is then used by the kube-bind backend to pass the ServiceAccount's kubeconfig (in the Backend cluster) to the App cluster securely: + 1. on the "Log in to dex" landing page, select "Log in with Example", + 2. on the "Grant Access" page, click the "Grant Access" button, + 3. lastly, click "Bind" when the page displays the mangodb resource. + + Go back to the terminal where `kubectl bind` command was run, and you should see the following output: + ``` + 🔑 Successfully authenticated to http://${BACKEND_HOST_IP}:8080/export + 🔒 Created secret kube-bind/kubeconfig-x9bd5 for host https://${BACKEND_HOST_IP}:34595, namespace kube-bind-gfsqn + 🚀 Executing: kubectl bind apiservice --remote-kubeconfig-namespace kube-bind --remote-kubeconfig-name kubeconfig-x9bd5 -f - + ✨ Use "-o yaml" and "--dry-run" to get the APIServiceExportRequest. + and pass it to "kubectl bind apiservice" directly. Great for automation. + 🚀 Deploying konnector v0.4.6 to namespace kube-bind. + Waiting for the konnector to be ready.............. + ✅ Created APIServiceBinding mangodbs.mangodb.com + + NAME PROVIDER READY MESSAGE AGE + apiservicebinding.kube-bind.io/mangodbs.mangodb.com False Pending 0s + ``` + + ### Step two: demo time! + + Let's see if we have CRDs for the MangoDB resource: + + ```sh + $ kubectl get crds + NAME CREATED AT + apiservicebindings.kube-bind.io 2024-12-19T08:46:13Z + mangodbs.mangodb.com 2024-12-19T08:46:17Z + ``` + + We do! Now create a CR for it: + + ```sh + kubectl create -f - << EOF_MangoDBDefinition + apiVersion: mangodb.com/v1alpha1 + kind: MangoDB + metadata: + name: my-db + spec: + tokenSecret: my-secret + region: eu-west-1 + tier: Shared + EOF_MangoDBDefinition + + kubectl describe mangodb my-db + ``` + + And finally, switch to the backend cluster and see that the CR is mirrored there: + ```sh + $ kubectl config use-context kind-backend + Switched to context "kind-backend". + # Your "kube-bind--default" will be different. + $ kubectl -n kube-bind-rp2s9-default describe mangodb my-db + Name: my-db + Namespace: kube-bind-rp2s9-default + Labels: + Annotations: + API Version: mangodb.com/v1alpha1 + Kind: MangoDB + Metadata: + Creation Timestamp: 2024-12-19T08:48:07Z + Generation: 1 + Resource Version: 1564 + UID: bed9f6d6-79d5-4535-8b20-690470b23378 + Spec: + Backup: false + Region: eu-west-1 + Tier: Shared + Token Secret: my-secret + Events: + ``` + + ### Step three: clean up + + Once you're done, you may clean up the setup simply by deleting the two kind clusters: + + ```sh + kind delete cluster --name backend + kind delete cluster --name app + ``` diff --git a/docs/content/developers/index.md b/docs/content/developers/index.md index 73437b84b..5e290d829 100644 --- a/docs/content/developers/index.md +++ b/docs/content/developers/index.md @@ -1 +1,6 @@ # Developers + +Welcome to the kube-bind developer documentation! This section contains information for developers who want to contribute to the kube-bind project, including guides on setting up a development environment, understanding the architecture, and contributing code, and API documentation. + +## Developer Guide + diff --git a/docs/content/contributing/guides/publishing-a-new-kube-bind-release.md b/docs/content/developers/publishing-a-release.md similarity index 95% rename from docs/content/contributing/guides/publishing-a-new-kube-bind-release.md rename to docs/content/developers/publishing-a-release.md index c9e361e0c..c1e746238 100644 --- a/docs/content/contributing/guides/publishing-a-new-kube-bind-release.md +++ b/docs/content/developers/publishing-a-release.md @@ -59,12 +59,10 @@ kube-bind has 3 go modules, and a unique tag is needed for each module every tim ## If it's a New Minor Version -```shell If this is the first release of a new minor version (e.g. the last release was v0.7.x, and you are releasing the first 0.8.x version), follow the following steps. Otherwise, you can skip to [Generate release notes](#generate-release-notes). -``` ## Generate Release Notes @@ -78,7 +76,7 @@ go install k8s.io/release/cmd/release-notes@latest To use `release-notes` you will need to generate a GitHub API token (Settings -> Developers settings -> Personal access tokens -> Fine-grained tokens). A token with _Public Repositories (read-only)_ repository access and no further permissions is sufficient. Store the token somewhere safe and export it as `GITHUB_TOKEN` environment variable. -Then, run run the `release-notes` tool (set `PREV_VERSION` to the version released before the one you have just released). +Then, run the `release-notes` tool (set `PREV_VERSION` to the version released before the one you have just released). ```shell TAG=v0.5.0 @@ -109,7 +107,7 @@ The [goreleaser](https://github.com/kube-bind/kube-bind/actions/workflows/gorele Documentation for the respective release branch needs to be triggered manually after the release branch has been pushed. 1. Navigate to the [Generate and push docs](https://github.com/kube-bind/kube-bind/actions/workflows/docs-gen-and-push.yaml) GitHub Action. -2. Hit the "Run forkflow" button, run workflow against `release-$VERSION`. +2. Hit the "Run workflow" button, run workflow against `release-$VERSION`. 3. Make sure the triggered workflow ran and deployed a new version of the documentation to [https://docs.kube-bind.io/main/](https://docs.kube-bind.io/main). ## Notify diff --git a/docs/content/high-level.png b/docs/content/high-level.png new file mode 100644 index 000000000..4cbbcf430 Binary files /dev/null and b/docs/content/high-level.png differ diff --git a/docs/content/index.md b/docs/content/index.md index 8facfcb1a..cf682edd9 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -1,21 +1,18 @@ # kube-bind Documentation -## Overview +## Overview -kube-bind is a prototype project that aims to provide better support for service providers and consumers that reside in distinct Kubernetes clusters. +kube-bind is a project that aims to provide better support for service providers and consumers that reside in distinct Kubernetes clusters. +We are actively working towards a stable release, and welcome feedback from the community. -- A service provider defines its API in terms of CRDs and associated permission claims/limitations, and exports it for use from other clusters. -- Service consumers identify the services they want to consume. +![High-level architecture diagram](high-level.png) + +- A service provider defines its API contract in terms of CRDs and associated permission claims/limitations, and exports it for use from other clusters. +- Service consumers identify the services they want to consume using CLI or Web UI. - The service CRDs get installed in the service consumer clusters, with objects of the defined kinds written and read by the service consumers. - The service provider indirectly reads and writes those objects as the interface to the service that it provides. - The service provider does not inject controllers/operators into the service consumer's cluster. -- A single vendor-neutral, OpenSource agent per consumer cluster connects it with the requested services. - -## Key Features -- **Enhanced Permission Claims**: Granular resource access with both label selectors and named resource support -- **Multi-backend Support**: Works with standard Kubernetes and kcp backends through multicluster-runtime -- **Secure Communication**: TLS-encrypted channels between service consumers and providers -- **Flexible UI**: Web-based dashboard for managing services and permissions when binding services +- A single vendor-neutral, OpenSource agent - `konnector` per consumer cluster connects it with the requested services. ## Quickstart @@ -33,4 +30,4 @@ There are several ways to communicate with us: - The [`#kube-bind` channel](https://kubernetes.slack.com/archives/C046PRXNJ4W) in the [Kubernetes Slack workspace](https://slack.k8s.io). - Our mailing lists: - [kube-bind-dev](https://groups.google.com/g/kube-bind-dev) for development discussions. -- By joining the kcp-dev mailing list, you should receive an invite to our bi-weekly community meetings. \ No newline at end of file +- By joining the kube-bind-dev mailing list, you should receive an invite to our bi-weekly community meetings. \ No newline at end of file diff --git a/docs/content/setup/.pages b/docs/content/setup/.pages index 5f0c6ac8a..e7c89b2c2 100644 --- a/docs/content/setup/.pages +++ b/docs/content/setup/.pages @@ -2,5 +2,4 @@ nav: - index.md - kubectl-plugin.md - quickstart.md - - local-setup-with-kind.md - helm.md \ No newline at end of file diff --git a/docs/content/setup/helm.md b/docs/content/setup/helm.md index dabcbdc1b..4e9cafb96 100644 --- a/docs/content/setup/helm.md +++ b/docs/content/setup/helm.md @@ -50,11 +50,11 @@ The following prerequisites are required. Click the links below for detailed set kube-bind oci://ghcr.io/kube-bind/charts/backend --version ${VERSION} # Or install a specific development version - helm upgrade --install \ - --namespace kube-bind \ - --create-namespace \ - --values ./deploy/charts/backend/examples/values-local-development.yaml \ - kube-bind oci://ghcr.io/kube-bind/charts/backend --version 0.0.0-fadb9edd26c0202f4a9511ee9d71b9e5f43672b9 + helm upgrade --install \ + --namespace kube-bind \ + --create-namespace \ + --values ./deploy/charts/backend/examples/values-local-development.yaml \ + kube-bind oci://ghcr.io/kube-bind/charts/backend --version 0.0.0-fadb9edd26c0202f4a9511ee9d71b9e5f43672b9 ``` 4. **Seed with example resources (optional):** diff --git a/docs/content/setup/index.md b/docs/content/setup/index.md index 0be2c1680..a30754d8b 100644 --- a/docs/content/setup/index.md +++ b/docs/content/setup/index.md @@ -6,35 +6,7 @@ kube-bind supports multiple deployment scenarios and backend providers to meet d ### Standard Kubernetes Setup -- **[Quickstart](quickstart.md)**: Get started quickly with the default provider +- **[kubectl plugin](kubectl-plugin.md)**: Install and use the kubectl-bind plugin +- **[Quickstart](quickstart.md)**: Get started quickly with a minimal setup - **[Helm Deployment](helm.md)**: Production deployment using Helm charts -- **[Local Setup with Kind](local-setup-with-kind.md)**: Local development environment -- **[kubectl Plugin](kubectl-plugin.md)**: Install and use the kubectl-bind plugin - -### Advanced Multi-Cluster Setup - -- **[kcp Integration](kcp-setup.md)**: Advanced multi-tenant setup with kcp workspaces and APIExports - -## Architecture Overview - -Starting with v0.5.0, kube-bind uses a multicluster-runtime architecture that supports: - -- **Multiple Providers**: Choose between standard Kubernetes or kcp backends -- **Enhanced API**: v1alpha2 API with resource-based exports and BoundSchema support -- **Flexible Deployment**: Support for various cluster topologies and requirements - -Choose the setup that best fits your use case: - -- Use **Quickstart** or **Local Setup with Kind** for development and testing -- Use **Helm Deployment** for production environments with standard Kubernetes -- Use **kcp Integration** for advanced multi-tenant scenarios with workspace isolation - -## Next Steps - -After completing your setup, explore these guides: - -- **[Usage Guide](../usage/index.md)**: Learn common workflows and the new Catalog API -- **[Migration Guide](../usage/migration.md)**: Upgrade from previous versions -- **[Developer Documentation](../developers/index.md)**: Understand the architecture and contribute - -{% include "partials/section-overview.html" %} +- **[Development Environment](../developers/dev-environments.md)**: Local development environment if you want to experiment with kube-bind on your machine diff --git a/docs/content/setup/kcp-setup.md b/docs/content/setup/kcp-setup.md index 8969c48b5..23e610477 100644 --- a/docs/content/setup/kcp-setup.md +++ b/docs/content/setup/kcp-setup.md @@ -12,7 +12,7 @@ This guide shows how to set up kube-bind with the kcp provider, which enables ad The kcp provider integrates kube-bind with [kcp](https://github.com/kcp-dev/kcp), enabling: - **Workspace-based isolation**: Each binding can operate in isolated kcp workspaces -- **Advanced multi-tenancy**: Provider and consumer separation through logical clusters where backend can be in single workspace or multiple workspaces +- **Advanced multi-tenancy**: Provider and consumer separation through logical clusters where the backend can be in a single workspace or multiple workspaces - **APIExport integration**: Leverages kcp's APIExport mechanism for service exposure - **Scalable architecture**: Supports large-scale multi-cluster deployments diff --git a/docs/content/setup/kubectl-plugin.md b/docs/content/setup/kubectl-plugin.md index ad106b855..ce24c4d31 100644 --- a/docs/content/setup/kubectl-plugin.md +++ b/docs/content/setup/kubectl-plugin.md @@ -3,13 +3,65 @@ description: > How to install and use the kubectl bind plugin. --- -# kubectl Plugins +# kubectl bind Plugin -kube-bind provides kubectl plugins to interact with kube-bind protocol. +The `kubectl bind` plugin is the primary command-line interface for interacting with kube-bind services. It provides both interactive web UI access and command-line binding capabilities for connecting to remote service providers. -or use [krew](https://krew.sigs.k8s.io/): +## Installation -```sh -kubectl krew index add bind https://github.com/kube-bind/krew-index.git -kubectl krew install bind/bind +=== "Krew" + + Install the plugin using [krew](https://krew.sigs.k8s.io/): + + ```bash + kubectl krew index add bind https://github.com/kube-bind/krew-index.git + kubectl krew install bind/bind + ``` + +=== "Manual Build" + + Build and install from source: + + ```bash + git clone https://github.com/kube-bind/kube-bind.git + cd kube-bind + make build + cp bin/kubectl-bind /usr/local/bin/ + ``` + +=== "Binary Download" + + Download pre-built binaries from the [releases page](https://github.com/kube-bind/kube-bind/releases): + + ```bash + # Download and install for Linux/macOS + curl -LO https://github.com/kube-bind/kube-bind/releases/latest/download/kubectl-bind-linux-amd64 + chmod +x kubectl-bind-linux-amd64 + sudo mv kubectl-bind-linux-amd64 /usr/local/bin/kubectl-bind + ``` + +## Basic Usage + +The main plugin command is `kubectl bind` which opens the kube-bind web UI in your browser for interactive service binding. + +```bash +# Login to a kube-bind server first +kubectl bind login https://my-kube-bind-server.example.com + +# Open kube-bind UI for current server context +kubectl bind ``` + +The plugin provides several subcommands including `login`, `templates`, `collections`, and `apiservice` for different binding workflows. + +For complete command reference and examples, see the [CLI Reference](../reference/index.md). + +## Quick Start + +1. Install the plugin using Krew or build from source +2. Login to your kube-bind server: `kubectl bind login ` +3. Open the web UI: `kubectl bind` +4. Browse and bind to available services through the interface + +For detailed setup instructions, see the [Quickstart Guide](./quickstart.md). + diff --git a/docs/content/setup/local-setup-with-kind.md b/docs/content/setup/local-setup-with-kind.md deleted file mode 100644 index d7122baf7..000000000 --- a/docs/content/setup/local-setup-with-kind.md +++ /dev/null @@ -1,322 +0,0 @@ -# Local kube-bind with kind - -This guide will walk you through setting up kube-bind between two Kubernetes clusters, where - -* **Backend cluster**: - * Deploys dex, cert-manager and kube-bind/backend - * Provides kube-bind compatible backend for MangoDB resources -* **App cluster**: - * Provides an application consuming MangoDBs - -## Pre-requisites - -To start, you'll need following tools available in your system or a VM: - -* [`kind`](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) -* [`kubectl`](https://kubernetes.io/docs/tasks/tools/) -* [`kubectl-bind`](https://github.com/kube-bind/kube-bind/releases/latest) (a kubectl plugin) -* [`helm`](https://helm.sh/docs/intro/quickstart/) -* [`jq`](https://jqlang.github.io/jq/download/) - -To install `kubectl-bind` plugin, please download the archive for your platform from the link above, extract it, and place the `kubectl-bind` executable in your system's `$PATH`. - -> Tip: In case of encountering `Too many open files` error when deploying the Kind clusters, run following commands: -> -> ```sh -> sudo sysctl fs.inotify.max_user_watches=524288 -> sudo sysctl fs.inotify.max_user_instances=512 -> ``` -> -> See the [kind documentation](https://kind.sigs.k8s.io/docs/user/known-issues/#pod-errors-due-to-too-many-open-files) for more details. - -## Provider cluster - -The provider cluster we'll prepare in this section will provide a kube-bind compatible backend that will provide a controller for a demo resource "MangoDB" we'll consume in another cluster later. - -> What is MangoDB? It is just an example CRD to demonstrate kube-bind's capabilities and testing, without any workloads. See its definition in [/test/e2e/bind/fixtures/provider/crd-mangodb.yaml](/test/e2e/bind/fixtures/provider/crd-mangodb.yaml). - -### Step one: create the Backend cluster - -First, stash the host's external IP in a variable as we're going to use it often: - -```sh -export BACKEND_HOST_IP="$(hostname -i | cut -d' ' -f1)" -``` - -Create a Kind cluster named "backend": - -```sh -cat << EOF_BackendClusterDefinition | kind create cluster --config=- -apiVersion: kind.x-k8s.io/v1alpha4 -kind: Cluster -name: backend -networking: - apiServerAddress: ${BACKEND_HOST_IP} -nodes: -- role: control-plane - extraPortMappings: - # MangoDB export endpoint - - containerPort: 30080 - hostPort: 8080 - protocol: TCP - # dex endpoint - - containerPort: 30556 - hostPort: 5556 - protocol: TCP -EOF_BackendClusterDefinition -``` - -> Note: the port mappings will become clear later on, but in general this setup is solely specific to how Kind exposes ports of its nodes on the host. Specifically, we're exposing ports from containers through NodePort services on Kind's nodes, and to make these ports available on the host we need to map them to host's ports through `extraPortMappings`. - -### Step two: deploy an identity provider - -kube-bind relies on OAuth2 for securely authenticating consumer and producer clusters. There are many ways to handle that in Kubernetes, for example with [dex IDP](https://github.com/dexidp/dex). It depends on cert-manager, which we'll deploy first: - -```sh -helm repo add jetstack https://charts.jetstack.io -helm install \ - --create-namespace \ - --namespace pki \ - --version v1.16.2 \ - --set crds.enabled=true \ - cert-manager jetstack/cert-manager -``` - -And now let's deploy dex: - -```sh -helm repo add dex https://charts.dexidp.io -cat << EOF_DEXDeploymentConfig | -config: - staticClients: - - id: kube-bind - redirectURIs: - - 'http://${BACKEND_HOST_IP}:8080/callback' - name: 'Kube Bind' - secret: ZXhhbXBsZS1hcHAtc2VjcmV0 - - issuer: http://${BACKEND_HOST_IP}:5556/dex - - storage: - type: kubernetes - config: - inCluster: true - - web: - http: 127.0.0.1:5556 - - telemetry: - http: 127.0.0.1:5558 - - grpc: - addr: 127.0.0.1:5557 - - connectors: - - type: mockCallback - id: mock - name: Example - - enablePasswordDB: true - staticPasswords: - - email: "admin@example.com" - hash: "\$2a\$10\$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W" - username: "admin" - userID: "08a8684b-db88-4b73-90a9-3cd1661f5466" -EOF_DEXDeploymentConfig -helm install \ - --create-namespace \ - --namespace idp \ - --set service.type=NodePort \ - --set service.ports.http.nodePort=30556 \ - dex dex/dex \ - -f - -``` - -### Step three: deploy the MangoDB kube-bind backend - -Now we'll deploy a kube-bind--compatible backend for MangoDB. Let's start with kube-bind CRDs: - -```sh -kubectl apply -f deploy/crd -``` - -And now CRDs for MangoDB: - -```sh -kubectl apply -f test/e2e/bind/fixtures/provider/crd-mangodb.yaml -``` - -To set up the MangoDB backend we'll need: -* ServiceAccount and ClusterRoleBinding for kube-bind's user, -* Deployment that runs the MangoDB backend -* Service that exposes the backend's address - -```sh -kubectl create namespace backend -# This is the address that will be used when generating kubeconfigs the App cluster, -# and so we need to be able to reach it from outside. -export BACKEND_KUBE_API_EXTERNAL_ADDRESS="$(kubectl config view --minify -o json | jq '.clusters[0].cluster.server' -r)" -# For demo example let's just bind "cluster-admin" ClusterRole to backend's "default" ServiceAccount. -kubectl create clusterrolebinding backend-admin --clusterrole cluster-admin --serviceaccount backend:default -# Create a new Deployment for the MangoDB backend. -kubectl --namespace backend \ - create deployment mangodb \ - --image ghcr.io/kube-bind/backend:v0.5.0 \ - --port 8080 \ - -- /ko-app/backend \ - --listen-address 0.0.0.0:8080 \ - --external-address "${BACKEND_KUBE_API_EXTERNAL_ADDRESS}" \ - --oidc-issuer-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 \ - --oidc-issuer-client-id=kube-bind \ - --oidc-issuer-url=http://${BACKEND_HOST_IP}:5556/dex \ - --oidc-callback-url=http://${BACKEND_HOST_IP}:8080/callback \ - --pretty-name="BigCorp.com" \ - --namespace-prefix="kube-bind-" \ - --cookie-signing-key=bGMHz7SR9XcI9JdDB68VmjQErrjbrAR9JdVqjAOKHzE= \ - --cookie-encryption-key=wadqi4u+w0bqnSrVFtM38Pz2ykYVIeeadhzT34XlC1Y= -# Expose mangodb's container port 8080 as a NodePort at 30080. We've already configured -# Kind to expose 30800 at host's 8080. -kubectl --namespace backend \ - create service nodeport mangodb \ - --tcp 8080 \ - --node-port 30080 -``` - -And that's really all there's to it. After that, you should see a kubectl output similar to this: - -```shell -$ kubectl --namespace backend get all -NAME READY STATUS RESTARTS AGE -pod/mangodb-6ff44cbbf-x7cjm 1/1 Running 0 100s - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/mangodb NodePort 10.96.10.212 8080:30080/TCP 100s - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/mangodb 1/1 1 1 100s - -NAME DESIRED CURRENT READY AGE -replicaset.apps/mangodb-6ff44cbbf 1 1 1 100s -``` - -## Consumer App cluster - -The App cluster will consume MangoDB CRs provided by the Backend. - -### Step one: create the App cluster - -Again, let's start by stashing the host's external IP in a variable as we're going to use it often (possibly the same one as for the Backend cluster): - -```sh -export APP_HOST_IP="$(hostname -i | cut -d' ' -f1)" -``` - -Create a Kind cluster named "app": - -```sh -cat << EOF_AppClusterDefinition | kind create cluster --config=- -apiVersion: kind.x-k8s.io/v1alpha4 -kind: Cluster -name: app -networking: - apiServerAddress: ${APP_HOST_IP} -EOF_AppClusterDefinition -``` - -### Binding MangoDB backend - -Now we'll bring in MangoDB CRDs from the Backend cluster (you can run `kubectl get crds` to see there are none yet): - -```sh -$ kubectl bind http://${BACKEND_HOST_IP}:8080/export -DISCLAIMER: This is a prototype. It will change in incompatible ways at any time. - -📦 Created kube-bind namespace. - - - -To authenticate, visit in your browser: - - http://${BACKEND_HOST_IP}:8080/authorize?c=3QnoGw&p=39595&s=b2YLH6 -``` - -The client is now waiting for you to visit the address similar to the one displayed in the output above. After completing the steps to create an OAuth2 token, it is then used by the kube-bind backend to pass the ServiceAccount's kubeconfig (in the Backend cluster) to the App cluster securely: -1. on the "Log in to dex" landing page, select "Log in with Example", -2. on the "Grant Access" page, click the "Grant Access" button, -3. lastly, click "Bind" when the page displays the mangodb resource. - -Go back to the terminal where `kubectl bind` command was run, and you should see the following output: -``` -🔑 Successfully authenticated to http://${BACKEND_HOST_IP}:8080/export -🔒 Created secret kube-bind/kubeconfig-x9bd5 for host https://${BACKEND_HOST_IP}:34595, namespace kube-bind-gfsqn -🚀 Executing: kubectl bind apiservice --remote-kubeconfig-namespace kube-bind --remote-kubeconfig-name kubeconfig-x9bd5 -f - -✨ Use "-o yaml" and "--dry-run" to get the APIServiceExportRequest. - and pass it to "kubectl bind apiservice" directly. Great for automation. -🚀 Deploying konnector v0.4.6 to namespace kube-bind. - Waiting for the konnector to be ready.............. -✅ Created APIServiceBinding mangodbs.mangodb.com - -NAME PROVIDER READY MESSAGE AGE -apiservicebinding.kube-bind.io/mangodbs.mangodb.com False Pending 0s -``` - -### Step two: demo time! - -Let's see if we have CRDs for the MangoDB resource: - -```sh -$ kubectl get crds -NAME CREATED AT -apiservicebindings.kube-bind.io 2024-12-19T08:46:13Z -mangodbs.mangodb.com 2024-12-19T08:46:17Z -``` - -We do! Now create a CR for it: - -```sh -kubectl create -f - << EOF_MangoDBDefinition -apiVersion: mangodb.com/v1alpha1 -kind: MangoDB -metadata: - name: my-db -spec: - tokenSecret: my-secret - region: eu-west-1 - tier: Shared -EOF_MangoDBDefinition -kubectl describe mangodb my-db -``` - -And finally, switch to the backend cluster and see that the CR is mirrored there: -```sh -$ kubectl config use-context kind-backend -Switched to context "kind-backend". -# Your "kube-bind--default" will be different. -$ kubectl -n kube-bind-rp2s9-default describe mangodb my-db -Name: my-db -Namespace: kube-bind-rp2s9-default -Labels: -Annotations: -API Version: mangodb.com/v1alpha1 -Kind: MangoDB -Metadata: - Creation Timestamp: 2024-12-19T08:48:07Z - Generation: 1 - Resource Version: 1564 - UID: bed9f6d6-79d5-4535-8b20-690470b23378 -Spec: - Backup: false - Region: eu-west-1 - Tier: Shared - Token Secret: my-secret -Events: -``` - -### Step three: clean up - -Once you're done, you may clean up the setup simply by deleting the two kind clusters: - -```sh -kind delete cluster --name backend -kind delete cluster --name app -``` diff --git a/docs/content/setup/quickstart.md b/docs/content/setup/quickstart.md index b6cd08022..1da0e69cb 100644 --- a/docs/content/setup/quickstart.md +++ b/docs/content/setup/quickstart.md @@ -8,129 +8,27 @@ description: > ## Prerequisites - [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) +- [kube-bind CLI](kubectl-plugin.md) installed ## Start with kube-bind -This section allows you to run local kube-bind backend and konnector with the standard Kubernetes provider. +### Deploy a kube-bind Backend -Starting with v0.5.0, kube-bind supports multiple backend providers through multicluster-runtime: +You can deploy a kube-bind backend using helm (recommended): -- **Standard Provider** (default): Works with regular Kubernetes clusters -- **kcp Provider**: Advanced multi-tenant setup with kcp workspaces (see [kcp Setup Guide](kcp-setup.md)) +- **[Using Helm Chart](helm.md)** - Recommended for production deployments -This quickstart uses the default provider. For kcp integration, see the [kcp Setup Guide](kcp-setup.md). +## Once you have a kube-bind backend running, you can connect to it using the `kubectl bind` plugin. -### Using kcp for Local Development +### Connect to kube-bind Server -For local development, we use [kcp](https://github.com/kcp-dev/kcp) to create multiple logical clusters under a single kcp instance, making them available and accessible via the same URL. - -To run kcp, you need to have a kcp binary. - -```shell -$ make run-kcp -``` - -To run the current backend, there must be an OIDC issuer installed in place to do the -the oauth2 workflow. - -We use dex to manage OIDC, following the steps below you can run a local OIDC issuer using dex: - -* First, clone the dex repo: `git clone https://github.com/dexidp/dex.git` -* `cd dex` and then build the dex binary `make build` -* The binary will be created in `bin/dex` -* Adjust the config file(`examples/config-dev.yaml`) for dex by specifying the server callback method: - ```yaml - staticClients: - - id: kube-bind - redirectURIs: - - 'http://127.0.0.1:8080/callback' - name: 'Kube Bind' - secret: ZXhhbXBsZS1hcHAtc2VjcmV0 - ``` -* Run dex: `./bin/dex serve examples/config-dev.yaml` - -Next you should be able to run the backend. For it you need a kubernetes cluster (e.g. kind) -accessible. - -***Note: make sure before running the backend that you have the dex server up and running as mentioned above -and that you have at least one k8s cluster. Take a look at the backend option in the cmd/main.go file*** - -Create copy of kcp kubeconfig and create provider cluster: - -```shell -cp .kcp/admin.kubeconfig .kcp/provider.kubeconfig -export KUBECONFIG=.kcp/provider.kubeconfig -kubectl ws create provider --enter -``` - -* apply the CRDs: - - ```shell - kubectl apply -f deploy/crd - ``` -* In order to populate binding list on website, we need a CRD with label `kube-bind.io/exported: true`. Apply example APIResourceSchema for the CRD: `kubectl apply -f deploy/examples/crd-mangodb.yaml` - - ```shell - kubectl apply -f deploy/examples/crd-mangodb.yaml - kubectl apply -f deploy/examples/crd-foo.yaml - kubectl apply -f deploy/examples/template-mangodb.yaml - kubectl apply -f deploy/examples/template-foo.yaml - kubectl apply -f deploy/examples/collection.yaml - ``` - -* start the backend binary with the right flags: - ```shell - make build - - bin/backend \ - --oidc-issuer-client-secret=ZXhhbXBsZS1hcHAtc2VjcmV0 \ - --oidc-issuer-client-id=kube-bind \ - --oidc-issuer-url=http://127.0.0.1:5556/dex \ - --oidc-callback-url=http://127.0.0.1:8080/api/callback \ - --pretty-name="BigCorp.com" \ - --namespace-prefix="kube-bind-" \ - --cookie-signing-key=bGMHz7SR9XcI9JdDB68VmjQErrjbrAR9JdVqjAOKHzE= \ - --cookie-encryption-key=wadqi4u+w0bqnSrVFtM38Pz2ykYVIeeadhzT34XlC1Y= \ - --consumer-scope=cluster - ``` - -where `ZXhhbXBsZS1hcHAtc2VjcmV0` matches the value of the dex config file. - -The `--cookie-signing-key` and `--cookie-encryption-key` settings can be generated using: - -```shell -$ openssl rand -base64 32 -WQh88mNOY0Z3tLy1/WOud7qIEEBxz+POc4j8BsYenYo= -``` - -The `--cookie-signing-key` option is required and supports 32 and 64 byte lengths. -The `--cookie-encryption-key` option is optional and supports byte lengths of 16, 24, 32 for AES-128, AES-192, or AES-256. - -### Consumer - -Now create consumer cluster: - -```shell -export KUBECONFIG=.kcp/admin.kubeconfig -kubectl ws create consumer --enter -``` - -Now create the APIServiceExportRequest: - -```shell -./bin/kubectl-bind http://127.0.0.1:8080 --dry-run -o yaml > apiserviceexport.yaml - -# This will wait for konnector to be ready. Once this gets running - start the konnector bellow -# IMPORTANT: Check namespace to be used! -./bin/kubectl-bind apiservice --remote-kubeconfig .kcp/provider.kubeconfig -f apiserviceexport.yaml --skip-konnector --remote-namespace - -# run konnector in different terminal -export KUBECONFIG=.kcp/admin.kubeconfig -go run ./cmd/konnector/ --lease-namespace default -``` +```bash +kubectl bind login https://my-kube-bind-server.example.com +``` -Create mangoDB object: +### Open kube-bind Web UI and bind services ```bash -kubectl create -f deploy/examples/mangodb.yaml +kubectl bind ``` + diff --git a/docs/content/usage/.pages b/docs/content/usage/.pages deleted file mode 100644 index 33aedbeff..000000000 --- a/docs/content/usage/.pages +++ /dev/null @@ -1,4 +0,0 @@ -title: Usage -nav: - - index.md - - migration.md \ No newline at end of file diff --git a/docs/content/usage/index.md b/docs/content/usage/index.md deleted file mode 100644 index 3078d7aa2..000000000 --- a/docs/content/usage/index.md +++ /dev/null @@ -1,16 +0,0 @@ -# Usage Guide - -This guide covers common usage patterns and workflows for kube-bind, including the new Catalog API features introduced in recent versions. - -## Table of Contents - -- [Basic Service Binding](#basic-service-binding) -- [Using the Catalog API](#using-the-catalog-api) -- [Permission Claims](#permission-claims) -- [Provider-side Namespace Management](#provider-side-namespace-management) -- [Advanced Workflows](#advanced-workflows) - -## Basic Service Binding - - -TODO \ No newline at end of file diff --git a/docs/content/usage/migration.md b/docs/content/usage/migration.md deleted file mode 100644 index 0d837b68f..000000000 --- a/docs/content/usage/migration.md +++ /dev/null @@ -1,24 +0,0 @@ -# Migration Guide - -This guide helps you migrate from older versions of kube-bind to the latest version with new features and API changes. - -## Migration Timeline - -### From v0.5.x to v0.6.x+ - -The v0.6.x release introduces several significant improvements: - -- **Catalog API**: New `Collection` and `APIServiceExportTemplate` CRDs for better service organization -- **Enhanced Permission Claims**: Support for `NamedResources` alongside label selectors -- **Provider-side Namespace Management**: Automatic RBAC and namespace provisioning -- **Improved kcp Integration**: Better workspace and APIExport handling - -## API Changes - -TODO - -If you encounter issues during migration: - -1. **Check GitHub Issues**: [kube-bind issues](https://github.com/kube-bind/kube-bind/issues) -2. **Slack Channel**: [`#kube-bind` on Kubernetes Slack](https://kubernetes.slack.com/archives/C046PRXNJ4W) -3. **Mailing List**: [kube-bind-dev](https://groups.google.com/g/kube-bind-dev) diff --git a/docs/generators/crd-ref/config.yaml b/docs/generators/crd-ref/config.yaml index ee10c4df1..1fde36617 100644 --- a/docs/generators/crd-ref/config.yaml +++ b/docs/generators/crd-ref/config.yaml @@ -49,3 +49,28 @@ source_repositories: - https://github.com/kube-bind/kube-bind topics: - apis + apiconversions.kube-bind.io: + owner: + - https://github.com/kube-bind/kube-bind + topics: + - apis + apiserviceexporttemplates.kube-bind.io: + owner: + - https://github.com/kube-bind/kube-bind + topics: + - apis + bindableresourcesrequests.kube-bind.io: + owner: + - https://github.com/kube-bind/kube-bind + topics: + - apis + boundschemas.kube-bind.io: + owner: + - https://github.com/kube-bind/kube-bind + topics: + - apis + collections.kube-bind.io: + owner: + - https://github.com/kube-bind/kube-bind + topics: + - apis diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 19b1bdcf4..2de75c2bd 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -104,6 +104,9 @@ markdown_extensions: format: !!python/name:pymdownx.superfences.fence_code_format # Enable note/warning/etc. callouts - admonition + # Enable content tabs + - pymdownx.tabbed: + alternate_style: true # Live reload if any of these change when running 'mkdocs serve' watch: diff --git a/docs/scripts/serve-docs.sh b/docs/scripts/serve-docs.sh index 1ddec77cc..d556a5b41 100755 --- a/docs/scripts/serve-docs.sh +++ b/docs/scripts/serve-docs.sh @@ -35,4 +35,9 @@ fi MIKE_OPTIONS+=(--ignore-remote-status) mike set-default "${MIKE_OPTIONS[@]}" main --allow-undefined -mike serve "${MIKE_OPTIONS[@]}" + +if [[ -n "${DEV_MODE:-}" ]]; then + mkdocs serve --dev-addr=127.0.0.1:8000 --livereload +else + mike serve "${MIKE_OPTIONS[@]}" +fi \ No newline at end of file diff --git a/sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go b/sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go index 1f8a39528..37d697db3 100644 --- a/sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go +++ b/sdk/apis/kubebind/v1alpha2/apiserviceexporttemplate_types.go @@ -23,6 +23,8 @@ import ( ) // APIServiceExportTemplate groups multiple CRDs with related resources (permissionClaims) as a Service definition. +// It is used by a web UI or CLI to allow users to select a set of resources to export from provider cluster to consumer cluster. +// This object is considered a static asset on the provider side and is not expected to change frequently. // // +crd // +genclient:nonNamespaced diff --git a/sdk/apis/kubebind/v1alpha2/boundchema_types.go b/sdk/apis/kubebind/v1alpha2/boundchema_types.go index ed39fc3c5..71d86ad72 100644 --- a/sdk/apis/kubebind/v1alpha2/boundchema_types.go +++ b/sdk/apis/kubebind/v1alpha2/boundchema_types.go @@ -31,7 +31,8 @@ import ( // Keys are "resource.group" for quick resolve (version is not part of the key). type ExportedSchemas map[string]*BoundSchema -// BoundSchema +// BoundSchema defines the schema of a bound API resource. It is created on the provider side to track +// CRD status on the consumer side by reflecting the CRD spec and status conditions. // +crd // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/sdk/apis/kubebind/v1alpha2/collection_types.go b/sdk/apis/kubebind/v1alpha2/collection_types.go index 060f16da1..64f0b060a 100644 --- a/sdk/apis/kubebind/v1alpha2/collection_types.go +++ b/sdk/apis/kubebind/v1alpha2/collection_types.go @@ -22,7 +22,8 @@ import ( conditionsapi "github.com/kube-bind/kube-bind/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" ) -// Collection groups multiple APIServiceExportTemplates into a logical group. This functions as a folder in the UI. +// Collection groups multiple APIServiceExportTemplates into a logical group. This functions as a grouping mechanism +// in UIs or CLIs to allow users to select a set of resources to export from provider cluster to consumer cluster. // // +crd // +genclient