Skip to content

Commit e537e8a

Browse files
committed
adjust binding
1 parent 6e7b07c commit e537e8a

4 files changed

Lines changed: 29 additions & 93 deletions

File tree

cli/pkg/kubectl/base/options.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ func (o *Options) Complete(skipValidate bool) error {
172172
// This should never happen. This is programming error.
173173
return fmt.Errorf("failed to resolve server configuration")
174174
}
175+
176+
o.Server = s.URL
177+
o.Cluster = s.Cluster
175178
o.server = s
176179
o.config = c
177180

cli/pkg/kubectl/bind-apiservice/plugin/bind.go

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import (
3636
"k8s.io/component-base/logs"
3737
logsv1 "k8s.io/component-base/logs/api/v1"
3838

39-
"github.com/kube-bind/kube-bind/cli/pkg/client"
4039
"github.com/kube-bind/kube-bind/cli/pkg/kubectl/base"
4140
kubebindv1alpha2 "github.com/kube-bind/kube-bind/sdk/apis/kubebind/v1alpha2"
4241
)
@@ -64,6 +63,7 @@ type BindAPIServiceOptions struct {
6463
NoBanner bool
6564
DryRun bool
6665
Template string
66+
Name string
6767
}
6868

6969
// NewBindAPIServiceOptions returns new BindAPIServiceOptions.
@@ -98,6 +98,9 @@ func (b *BindAPIServiceOptions) AddCmdFlags(cmd *cobra.Command) {
9898

9999
// Complete ensures all fields are initialized.
100100
func (b *BindAPIServiceOptions) Complete(args []string) error {
101+
if len(args) > 0 {
102+
b.Name = args[0]
103+
}
101104
if err := b.Options.Complete(false); err != nil {
102105
return err
103106
}
@@ -130,6 +133,9 @@ func (b *BindAPIServiceOptions) Validate() error {
130133
return errors.New("remote-kubeconfig or remote-kubeconfig-namespace and remote-kubeconfig-name are required")
131134
}
132135
}
136+
if b.Name == "" {
137+
return errors.New("name is required")
138+
}
133139

134140
return b.Options.Validate()
135141
}
@@ -271,9 +277,18 @@ func (b *BindAPIServiceOptions) bindTemplate(ctx context.Context) (*bindTemplate
271277
return nil, fmt.Errorf("failed to create authenticated client: %w", err)
272278
}
273279

274-
bindResponse, err := getBindResponse(ctx, client, b.Template)
280+
bindRequest := &kubebindv1alpha2.BindableResourcesRequest{
281+
ObjectMeta: metav1.ObjectMeta{
282+
Name: b.Name,
283+
},
284+
TemplateRef: kubebindv1alpha2.APIServiceExportTemplateRef{
285+
Name: b.Template,
286+
},
287+
}
288+
289+
bindResponse, err := client.Bind(ctx, bindRequest)
275290
if err != nil {
276-
return nil, fmt.Errorf("failed to bind template: %w", err)
291+
return nil, fmt.Errorf("failed to bind to template %q: %w", b.Template, err)
277292
}
278293

279294
if bindResponse.Authentication.OAuth2CodeGrant == nil {
@@ -299,7 +314,7 @@ func (b *BindAPIServiceOptions) bindTemplate(ctx context.Context) (*bindTemplate
299314
return nil, err
300315
}
301316
if created {
302-
fmt.Fprintf(b.Options.IOStreams.ErrOut, "reated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace)
317+
fmt.Fprintf(b.Options.IOStreams.ErrOut, "Created secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace)
303318
} else {
304319
fmt.Fprintf(b.Options.IOStreams.ErrOut, "Updated secret %s/%s for host %s, namespace %s\n", "kube-bind", secret.Name, remoteHost, remoteNamespace)
305320
}
@@ -309,17 +324,3 @@ func (b *BindAPIServiceOptions) bindTemplate(ctx context.Context) (*bindTemplate
309324
name: secret.Name,
310325
}, nil
311326
}
312-
313-
// getBindResponse retrieves the binding response for a template.
314-
func getBindResponse(ctx context.Context, client client.Client, templateName string) (*kubebindv1alpha2.BindingResourceResponse, error) {
315-
bindRequest := &kubebindv1alpha2.BindableResourcesRequest{
316-
ObjectMeta: metav1.ObjectMeta{
317-
Name: "bind-request",
318-
},
319-
TemplateRef: kubebindv1alpha2.APIServiceExportTemplateRef{
320-
Name: templateName,
321-
},
322-
}
323-
324-
return client.Bind(ctx, bindRequest)
325-
}

cli/pkg/kubectl/bind/plugin/bind.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"net/url"
2828
"os/exec"
2929
"strconv"
30-
"strings"
3130
"time"
3231

3332
"github.com/spf13/cobra"
@@ -62,19 +61,12 @@ type BindOptions struct {
6261
printer printers.ResourcePrinter
6362
DryRun bool
6463

65-
// url is the argument accepted by the command. It contains the
66-
// reference to where an APIService exists.
67-
URL string
68-
6964
// skipKonnector skips the deployment of the konnector.
7065
SkipKonnector bool
7166

7267
// The konnector image to use and override default konnector image
7368
KonnectorImageOverride string
7469

75-
// Cluster is the cluster ID to use for binding (optional)
76-
Cluster string
77-
7870
// Runner is runs the command. It can be replaced in tests.
7971
Runner func(cmd *exec.Cmd) error
8072

@@ -128,12 +120,12 @@ func (b *BindOptions) Complete(args []string) error {
128120

129121
// Validate validates the BindOptions are complete and usable.
130122
func (b *BindOptions) Validate() error {
131-
if b.URL == "" {
132-
return fmt.Errorf("server URL is required - this should not happen after Complete()")
123+
if b.Server == "" {
124+
return fmt.Errorf("server is required")
133125
}
134126

135-
if _, err := url.Parse(b.URL); err != nil {
136-
return fmt.Errorf("invalid url %q: %w", b.URL, err)
127+
if _, err := url.Parse(b.Server); err != nil {
128+
return fmt.Errorf("invalid url %q: %w", b.Server, err)
137129
}
138130

139131
return b.Options.Validate()
@@ -264,10 +256,8 @@ func (b *BindOptions) runWithCallback(ctx context.Context, _ chan<- string) erro
264256

265257
// buildUIURL constructs the UI URL with callback parameters
266258
func (b *BindOptions) buildUIURL(callbackPort int, sessionID, clusterID string) (string, error) {
267-
baseURL := strings.TrimSuffix(b.URL, "/")
268-
269259
// Parse the base URL
270-
u, err := url.Parse(baseURL)
260+
u, err := url.Parse(b.Server)
271261
if err != nil {
272262
return "", fmt.Errorf("invalid server URL: %w", err)
273263
}

docs/content/setup/kcp-setup.md

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -165,23 +165,8 @@ kubectl ws create consumer --enter
165165
Generate the APIServiceExport YAML:
166166

167167
```bash
168-
./bin/kubectl-bind http://127.0.0.1:8080/clusters/<logical-cluster-id>/exports --dry-run -o yaml > apiserviceexport.yaml
169-
```
170-
171-
Extract the kubeconfig for binding:
172-
173-
```bash
174-
kubectl get secret <secret-name> -n kube-bind -o jsonpath='{.data.kubeconfig}' | base64 -d > remote.kubeconfig
175-
```
176-
177-
Perform the binding:
178-
179-
```bash
180-
./bin/kubectl-bind apiservice \
181-
--remote-kubeconfig remote.kubeconfig \
182-
-f apiserviceexport.yaml \
183-
--skip-konnector \
184-
--remote-namespace kube-bind-<random-suffix>
168+
./bin/kubectl-bind login http://127.0.0.1:8080 --cluster <logical-cluster-id>
169+
./bin/kubectl-bind --skip-konnector
185170
```
186171

187172
### 3. Start Konnector
@@ -198,46 +183,3 @@ Create example resources:
198183
```bash
199184
kubectl apply -f contrib/kcp/deploy/examples/cowboy.yaml
200185
```
201-
202-
## Advanced Features
203-
204-
### Multiple Consumers
205-
206-
You can create multiple consumer workspaces to test multi-tenant scenarios:
207-
208-
```bash
209-
# Create second consumer
210-
cp .kcp/admin.kubeconfig .kcp/consumer2.kubeconfig
211-
export KUBECONFIG=.kcp/consumer2.kubeconfig
212-
kubectl ws use :root
213-
kubectl ws create consumer2 --enter
214-
215-
# Repeat binding process with different namespace
216-
# Start konnector on different port
217-
go run ./cmd/konnector/ --lease-namespace default --server-address :8091
218-
```
219-
220-
### Debugging
221-
222-
To debug the setup, use the following commands:
223-
224-
```bash
225-
# Switch to debug workspace
226-
cp .kcp/admin.kubeconfig .kcp/debug.kubeconfig
227-
export KUBECONFIG=.kcp/debug.kubeconfig
228-
kubectl ws use :root:kube-bind
229-
230-
# Check available resources
231-
kubectl-s "$(kubectl get apiexportendpointslice kube-bind.io -o jsonpath="{.status.endpoints[0].url}")/clusters/*" api-resources
232-
233-
# List CRDs
234-
kubectl-s "$(kubectl get apiexportendpointslice kube-bind.io -o jsonpath="{.status.endpoints[0].url}")/clusters/*" get crd
235-
```
236-
237-
## Key Differences from Standard Setup
238-
239-
- **Provider Selection**: Uses `--multicluster-runtime-provider kcp` flag
240-
- **Workspace Management**: Requires kcp workspace creation and management
241-
- **APIExport Integration**: Leverages kcp's APIExport mechanism to enable shared backed service.
242-
- **URL Structure**: Uses kcp-specific URLs with cluster identifiers. In production, this should be abstracted by a service wrapper.
243-
- **Advanced Isolation**: Provides workspace-level isolation beyond namespaces

0 commit comments

Comments
 (0)