Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/content/.pages
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ nav:
- index.md
- Setup: setup
- Contributing: contributing
- Developers: developers
- Reference: reference
4 changes: 4 additions & 0 deletions docs/content/developers/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nav:
- index.md
- Backend: backend
- Konnector: konnector
3 changes: 3 additions & 0 deletions docs/content/developers/backend/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
nav:
- index.md
- HTTP: http
3 changes: 3 additions & 0 deletions docs/content/developers/backend/http/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
nav:
- cluster-binding.md
- api-binding.md
50 changes: 50 additions & 0 deletions docs/content/developers/backend/http/api-binding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# API Binding

## Overview

```mermaid
sequenceDiagram
autonumber
participant consumer-cluster as Consumer cluster
participant client as Client
participant provider-cluster as Provider cluster
participant provider-backend as Provider backend


%% Create APIServiceExportRequest
client->>provider-cluster: Create "APIServiceExportRequest"

par Provider
provider-backend->>provider-cluster: Get "APIServiceExportRequest"
loop For each "APIServiceExportRequest.spec.resources"
provider-backend->>provider-cluster: Create "APIServiceExport"
end
provider-backend->>provider-cluster: Set "APIServiceExportRequest.status.phase"
and Client
loop Every 1 second for 10 minutes
client->>provider-cluster: Get "APIServiceExportRequest"
client->>client: Verify "APIServiceExportRequest"<br/>(.status.phase == Succeeded)"
end
end

%% Create APIServiceBindings
loop For each "APIServiceExportRequest.spec.resources"
client->>consumer-cluster: Create "APIServiceBinding"
end
```

## Contracts

**APIServiceExportRequest**

In case the _APIServiceExportRequest_ is accepted, the provider backend **must** ensure that

* for each `APIServiceExportRequest.spec.resources` an `APIServiceExport` is created
* each `APIServiceExport` is created in the namespace of the `APIServiceExportRequest`
* each `APIServiceExport` is created with a name following the pattern `resource.resource + "." + resource.group`
* the `APIServiceExportRequest.status.phase` is set to `Succeeded`

In case the _APIServiceExportRequest_ is declined, the provider backend **must** ensure that

* the `APIServiceExportRequest.status.terminalMessage` is set to a human readable message describing the reason
* the `APIServiceExportRequest.status.phase` is set to `Failed`
70 changes: 70 additions & 0 deletions docs/content/developers/backend/http/cluster-binding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Cluster Binding

## Overview

```mermaid
sequenceDiagram
autonumber
participant consumer-cluster as Consumer cluster
participant client as Client
participant provider-backend as Provider backend
participant authentication-provider as Authentication Provider

%% Get provider information
client->>+provider-backend: GET "${PROVIDER_BINDING_URL}"
provider-backend->>-client: 200 "BindingProvider"

client->>client: Verify "BindingProvider"

%% Authenticate to provider
client-->>authentication-provider: Authenticate to provider

%% Bind to API
provider-backend->>client: 200 "BindingResponse"

client->>consumer-cluster: Ensure kubeconfig secret

loop For each "BindingResponse.requests"
client->>consumer-cluster: Bind remote API to consumer cluster
end
```

## Contracts

**BindingResponse**

In case the cluster binding request is accepted, the provider backend **must** ensure that

* the kubeconfig returned in the `BindingResponse` contains a current context
* the configured current context points to the "cluster namespace"
* the `ClusterBinding` object named "cluster" exists in the "cluster namespace"
* the secret referenced by `ClusterBinding.spec.kubeconfigSecretRef.name` exists
* the key of the secret referenced by `ClusterBinding.spec.kubeconfigSecretRef.key` contains a valid kubeconfig
* the configured current context points to a user with at least the following permissions in the "cluster namespace" (here expressed as RBAC rules)
```yaml
- apiGroups: ["kube-bind.io"]
resources: ["apiserviceexportrequests"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]

- apiGroups: ["kube-bind.io"]
resources: ["apiserviceexports"]
verbs: ["get", "watch", "list"]
- apiGroups: ["kube-bind.io"]
resources: ["apiserviceexports/status"]
verbs: ["get", "patch", "update"]

- apiGroups: ["kube-bind.io"]
resources: ["apiservicenamespaces"]
verbs: ["create", "delete", "patch", "update", "get", "list", "watch"]

- apiGroups: ["kube-bind.io"]
resources: ["clusterbindings"]
verbs: ["get", "watch", "list"]
- apiGroups: ["kube-bind.io"]
resources: ["clusterbindings/status"]
verbs: ["get", "patch", "update"]

- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
```
1 change: 1 addition & 0 deletions docs/content/developers/backend/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Backend
1 change: 1 addition & 0 deletions docs/content/developers/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Developers
3 changes: 3 additions & 0 deletions docs/content/developers/konnector/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
nav:
- index.md
- Controllers: controllers
4 changes: 4 additions & 0 deletions docs/content/developers/konnector/controllers/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nav:
- konnector.md
- apiservicebinding.md
- Cluster: cluster
36 changes: 36 additions & 0 deletions docs/content/developers/konnector/controllers/apiservicebinding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# APIServiceBindings

The APIServiceBinding controller watches `APIServiceBindings` and the referenced `Secrets` in the **consumer
cluster**.

It is responsible for:

* validating the kubeconfig stored in the secrets referenced by `APIServiceBindings`

## Overview

```mermaid
flowchart TD
%% Nodes
start@{ shape: start }
stop@{ shape: stop }

enqueue_reconcile(["Enqueue reconcile call for APIServiceBinding"])

get_kubeconfig_secret(["Get referenced kubeconfig secret"])
is_kubeconfig_valid{"kubeconfig<br>valid?"}

set_condition_secret_valid_to_true(["Set condition 'SecretValid' to true"])
set_condition_secret_valid_to_false(["Set condition 'SecretValid' to false"])

%% Transitions
start --> enqueue_reconcile
enqueue_reconcile --> get_kubeconfig_secret
get_kubeconfig_secret --> is_kubeconfig_valid

is_kubeconfig_valid --> |yes| set_condition_secret_valid_to_true
is_kubeconfig_valid --> |no| set_condition_secret_valid_to_false

set_condition_secret_valid_to_true --> stop
set_condition_secret_valid_to_false --> stop
```
4 changes: 4 additions & 0 deletions docs/content/developers/konnector/controllers/cluster/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nav:
- clusterbinding.md
- apiservicenamespace.md
- apiservicebinding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# APIServiceBindings

The APIServiceBinding controller watches `APIServiceBindings`, and `CRDs` in the **consumer cluster** and `APIServiceExports` in the **provider cluster**.

It is responsible for:

* synchronizing `APIServiceExports` in the **provider cluster** to `CRDs` in the **consumer cluster**

## Overview

```mermaid
flowchart TD
%% Nodes
start@{ shape: start }
stop@{ shape: stop }

enqueue_reconcile(["Enqueue reconcile call for APIServiceBinding"])

is_apiservicebinding_owned{"binding<br>owned?"}
set_apiservicebinding_condition_connected_to_true(["Set condition 'Connected' to true"])
set_apiservicebinding_condition_connected_to_false(["Set condition 'Connected' to false"])
set_apiservicebinding_condition_schemainsync_to_true(["Set condition 'SchemaInSync' to true"])
set_apiservicebinding_condition_schemainsync_to_false(["Set condition 'SchemaInSync' to false"])

get_apiserviceexport(["Get APIServiceExport"])
convert_apiserviceexport_to_crd(["Convert APIServiceExport to CRD"])
is_apiserviceexport_present{"export<br>exists?"}
is_apiserviceexport_valid{"export<br>valid?"}

get_crd(["Get CRD"])
create_crd(["Create CRD"])
update_crd(["Update CRD"])
is_crd_present{"CRD<br>exists?"}
is_crd_owned{"CRD<br>owned?"}

get_clusterbinding(["Get ClusterBinding"])
set_apiservicebinding_provider_name(["Set provider name"])

%% Transitions
start --> enqueue_reconcile
enqueue_reconcile --> is_apiservicebinding_owned

is_apiservicebinding_owned --> |yes| get_apiserviceexport
get_apiserviceexport --> is_apiserviceexport_present
is_apiserviceexport_present --> |yes| set_apiservicebinding_condition_connected_to_true
is_apiserviceexport_present --> |no| set_apiservicebinding_condition_connected_to_false
set_apiservicebinding_condition_connected_to_true --> convert_apiserviceexport_to_crd
set_apiservicebinding_condition_connected_to_false --> stop

convert_apiserviceexport_to_crd --> is_apiserviceexport_valid
is_apiserviceexport_valid --> |yes| get_crd
is_apiserviceexport_valid --> |no| set_apiservicebinding_condition_schemainsync_to_false

get_crd --> is_crd_present
is_crd_present --> |no| create_crd
is_crd_present --> |yes| is_crd_owned
update_crd --> set_apiservicebinding_condition_schemainsync_to_true
create_crd --> set_apiservicebinding_condition_schemainsync_to_true

is_crd_owned --> |yes| update_crd
is_crd_owned --> |no| set_apiservicebinding_condition_schemainsync_to_false

set_apiservicebinding_condition_schemainsync_to_true --> get_clusterbinding
set_apiservicebinding_condition_schemainsync_to_false --> get_clusterbinding

get_clusterbinding --> set_apiservicebinding_provider_name

is_apiservicebinding_owned --> |no| stop
set_apiservicebinding_provider_name --> stop
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# APIServiceNamespaces

The APIServiceNamespace controller watches `Namespaces` in the **consumer cluster** and `APIServiceNamespaces` in the **provider cluster**.

It is responsible for:

* synchronizing `Namespaces` in the **consumer cluster** with `APIServiceNamespaces` in the **provider cluster**

## Overview

```mermaid
flowchart TD
%% Nodes
start@{ shape: start }
stop@{ shape: stop }

enqueue_reconcile(["Enqueue reconcile call for APIServiceNamespace"])

get_namespace(["Get associated namespace"])
is_namespace_present(["namespace<br>exists?"])

delete_api_service_namespace(["Delete APIServiceNamespace"])

%% Transitions
start --> enqueue_reconcile
enqueue_reconcile --> get_namespace
get_namespace --> is_namespace_present

is_namespace_present --> |yes| stop
is_namespace_present --> |no| delete_api_service_namespace
delete_api_service_namespace --> stop
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# ClusterBindings

The ClusterBinding controller watches `Secrets` (referenced by `APIServiceBindings`) in the **consumer
cluster** and `ClusterBindings`, the referenced `Secrets`, and `APIServiceExport` in the **provider
cluster**.

It is responsible for:

* synchronizing the secret referenced by the `ClusterBinding` in the **provider cluster** to the secret referenced by the `APIServiceBindings` in the **consumer cluster**
* reporting heartbeat to `ClusterBinding` in the **provider cluster**
* reporting konnector version `ClusterBinding` in the **provider cluster**
* reporting heartbeat to all `APIServiceBindings` managed by `ClusterBinding` in the **consumer cluster**

## Overview

```mermaid
flowchart TD
%% Nodes
start@{ shape: start }
stop@{ shape: stop }

enqueue_reconcile(["Enqueue reconcile call for ClusterBinding"])

update_cluster_binding(["Update ClusterBinding"])
is_cluster_binding_update_successful{"update<br>successful?"}

get_cluster_binding_kubeconfig_secret(["Get referenced provider kubeconfig secret"])
is_cluster_binding_kubeconfig_secret_valid{"secret<br>valid?"}

set_cluster_binding_condition_secret_valid_to_true(["Set condition 'SecretValid' to true"])
set_cluster_binding_condition_secret_valid_to_false(["Set condition 'SecretValid' to false"])
set_cluster_binding_condition_valid_version_to_true(["Set condition 'ValidVersion' to true"])
set_cluster_binding_condition_valid_version_to_false(["Set condition 'ValidVersion' to false"])
set_cluster_binding_condition_ready(["Set condition 'Ready' to summary"])

set_cluster_binding_status_last_heartbeat(["Set status 'LastHeartbeatTime' to now"])
set_cluster_binding_status_konnector_version(["Set status 'KonnectorVersion'"])

get_api_binding_kubeconfig_secret(["Get consumer kubeconfig secret"])
create_api_binding_kubeconfig_secret(["Create consumer kubeconfig secret"])
update_api_binding_kubeconfig_secret(["Update consumer kubeconfig secret"])
is_api_binding_kubeconfig_secret_present{"secret<br>exists?"}

set_api_binding_status_heartbeating_to_true(["Set APIServiceBinding conditions 'Heartbeating' to true"])
set_api_binding_status_heartbeating_to_false(["Set APIServiceBinding conditions 'Heartbeating' to false"])

get_konnector_version(["Get konnector version"])
is_konnector_version_valid{"version<br>valid?"}

%% Transitions
start --> enqueue_reconcile
enqueue_reconcile --> get_cluster_binding_kubeconfig_secret
get_cluster_binding_kubeconfig_secret --> is_cluster_binding_kubeconfig_secret_valid

is_cluster_binding_kubeconfig_secret_valid --> |yes| get_api_binding_kubeconfig_secret
get_api_binding_kubeconfig_secret --> is_api_binding_kubeconfig_secret_present
is_api_binding_kubeconfig_secret_present --> |yes| update_api_binding_kubeconfig_secret
is_api_binding_kubeconfig_secret_present --> |no| create_api_binding_kubeconfig_secret
update_api_binding_kubeconfig_secret --> set_cluster_binding_condition_secret_valid_to_true
create_api_binding_kubeconfig_secret --> set_cluster_binding_condition_secret_valid_to_true

is_cluster_binding_kubeconfig_secret_valid --> |no| set_cluster_binding_condition_secret_valid_to_false

set_cluster_binding_condition_secret_valid_to_true --> set_cluster_binding_status_last_heartbeat
set_cluster_binding_condition_secret_valid_to_false --> set_cluster_binding_status_last_heartbeat

set_cluster_binding_status_last_heartbeat --> get_konnector_version
get_konnector_version --> is_konnector_version_valid

is_konnector_version_valid --> |yes| set_cluster_binding_status_konnector_version
set_cluster_binding_status_konnector_version --> set_cluster_binding_condition_valid_version_to_true

is_konnector_version_valid --> |no| set_cluster_binding_condition_valid_version_to_false

set_cluster_binding_condition_valid_version_to_true --> set_cluster_binding_condition_ready
set_cluster_binding_condition_valid_version_to_false --> set_cluster_binding_condition_ready

set_cluster_binding_condition_ready --> update_cluster_binding
update_cluster_binding --> is_cluster_binding_update_successful

is_cluster_binding_update_successful --> |yes| set_api_binding_status_heartbeating_to_true
is_cluster_binding_update_successful --> |no| set_api_binding_status_heartbeating_to_false

set_api_binding_status_heartbeating_to_true --> stop
set_api_binding_status_heartbeating_to_false --> stop
```
Loading