Skip to content

Commit

Permalink
Add Kubernetes support
Browse files Browse the repository at this point in the history
## **Solution**

This pull request introduces a new container abstraction that consolidates Docker and Kubernetes container operations under a unified interface. The changes include:

* Renaming the package from "docker" to "container"
* Introducing the following core components:
  - **ContainerImpl**: Provides a unified interface to interact with container runtimes. It smartly selects between the Docker wrapper and a new Kubernetes wrapper based on the runtime environment.
  - **ContainerOpts**: Encapsulates container configuration options. In contrast to the old DockerOpts (which used maps for volumes and environment variables), the new design uses a slice for volumes and a map for environment variables. This makes it easier to manage and extend configurations.
  - **DockerOpts**: Now supports additional options such as restart policy and aligns with the new structure.
  - **K8sOpts**: Contains options specific to running containers in a Kubernetes cluster.

* Adaptations in application code:
  - In the Airbyte provider storage module, the previous `docker.DockerWrapper` has been replaced by the unified container implementation (`ContainerImpl`). This ensures that all container operations (e.g., volume mounting, environment variables, command execution) work consistently whether running in a Docker or Kubernetes environment.
  - In the DBT runner within the transformer registry, similar changes have been applied by replacing references to the old Docker abstraction with the new container abstraction.

* New Kubernetes wrapper implementation
  - A new wrapper (`K8sWrapper`) has been introduced. When the environment variable `KUBERNETES_SERVICE_HOST` is detected, the container implementation will instantiate the Kubernetes wrapper rather than the Docker one.
  - This wrapper provides methods for creating pods, retrieving logs, and deleting pods in a Kubernetes cluster, bridging the gap between local container operations and cloud-native orchestration.
  - Comprehensive testing has been added, including unit tests for the Kubernetes options and integration tests that create a temporary Kind cluster, where an actual pod is spawned to test log retrieval.

The diagrams below explain the flow and interactions of the new container abstraction:

### **1. Sequence Diagram**

**Purpose:** Illustrates the decision-making process of choosing the proper container runtime interface.

* The application creates a configuration using **ContainerOpts**.
* The helper function `NewContainerImpl(l)` checks if the environment variable `KUBERNETES_SERVICE_HOST` is set.
* If running in a Kubernetes environment, `NewK8sWrapper` is invoked to create a Kubernetes client.
* Otherwise, the system falls back to the traditional Docker wrapper via `NewDockerWrapper(l)`.
* **ContainerImpl** converts these options to the runtime-specific format and delegates to either the Docker or Kubernetes wrapper.
* The respective wrapper then pulls the image (if necessary) and runs the container/pod, returning logs and status.

```mermaid
flowchart TD
    A[Create ContainerOpts]
    B[NewContainerImpl]
    C{Is Kubernetes Environment?}
    D[NewK8sWrapper]
    E[NewDockerWrapper]
    F[Run Container/Pod]
    G[Return Logs & Status]

    A --> B
    B --> C
    C -- Yes --> D
    C -- No --> E
    D --> F
    E --> F
    F --> G
```

### **2. Class Diagram**

**Purpose:** Shows the relationships between key components managing container operations.

* The central **ContainerImpl** interface defines common methods such as Run() and Pull().
* The **DockerWrapper** and **K8sWrapper** implement the ContainerImpl interface.
* **ContainerOpts** encapsulates configuration shared between the two implementations.
* **K8sOpts** and **DockerOpts** serve as the runtime-specific configuration options.

```mermaid
classDiagram
    class ContainerImpl {
      +Run(ctx, opts ContainerOpts) (stdout io.Reader, stderr io.Reader, err error)
      +Pull(ctx, image string, opts ImagePullOptions) error
    }

    class DockerWrapper {
      +RunContainer(ctx, opts DockerOpts) (io.Reader, io.Reader, error)
      +Pull(ctx, image string, opts ImagePullOptions) error
    }

    class K8sWrapper {
      +Run(ctx, opts ContainerOpts) (io.Reader, io.Reader, error)
      +RunPod(ctx, opts K8sOpts) (*bytes.Buffer, error)
      +Pull(ctx, image string, opts ImagePullOptions) error
    }

    class ContainerOpts {
      +Env map[string]string
      +Volumes []Volume
      +LogDriver string
      +LogOptions map[string]string
      +Image string
      +Network string
      +ContainerName string
      +Command []string
      +Args []string
      +Timeout time.Duration
      +AttachStdout bool
      +AttachStderr bool
      +RestartPolicy string
    }

    class DockerOpts
    class K8sOpts

    ContainerImpl <|.. DockerWrapper
    ContainerImpl <|.. K8sWrapper
    ContainerOpts --> DockerOpts : convertTo()
    ContainerOpts --> K8sOpts : convertTo()
```

Let me know if further refinements are needed!

---

Pull Request resolved: #206

Co-authored-by: tserakhau <tserakhau@double.cloud>
Co-authored-by: tserakhau <tserakhau@double.cloud>
Co-authored-by: tserakhau <tserakhau@double.cloud>
Co-authored-by: tserakhau <tserakhau@double.cloud>
Co-authored-by: tserakhau <tserakhau@double.cloud>
Co-authored-by: tserakhau <tserakhau@double.cloud>
commit_hash:19988b16b4a75ec523f1e2476a60c890837066a0
  • Loading branch information
kamushadenes authored and robot-piglet committed Feb 18, 2025
1 parent 173effe commit fd08e3c
Show file tree
Hide file tree
Showing 18 changed files with 1,118 additions and 240 deletions.
22 changes: 19 additions & 3 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.22.5"
go-version: "1.22.0"
- shell: bash
run: |
make build
Expand All @@ -34,6 +34,12 @@ jobs:
# CLI test suites
{ group: "cmd", name: "cmd", path: "" },
# providers suites, some of the providers are too heavy to run as single test
{
group: "pkg/providers",
name: "container",
path: "container",
container: true,
},
{ group: "pkg/providers", name: "yt", path: "yt", yt: true },
{
group: "pkg/providers",
Expand All @@ -54,7 +60,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.22.5"
go-version: "1.22.0"
- shell: bash
run: |
go install gotest.tools/gotestsum@latest
Expand All @@ -69,6 +75,14 @@ jobs:
- shell: bash
run: |
pg_dump --version
- uses: engineerd/setup-kind@v0.6.0
if: matrix.suite.container
with:
version: "v0.26.0"
# Handled by the test code
skipClusterCreation: true
skipClusterDeletion: true
skipClusterLogsExport: true
- shell: bash
if: matrix.suite.yt
name: prepare local YT
Expand All @@ -80,6 +94,8 @@ jobs:
- shell: bash
run: |
make run-tests SUITE_GROUP="${{ matrix.suite.group }}" SUITE_PATH="${{ matrix.suite.path }}" SUITE_NAME="${{ matrix.suite.name }}"
env:
TEST_KUBERNETES_INTEGRATION: ${{ matrix.suite.container == true && '1' || '' }}
- name: Upload Test Results
uses: actions/upload-artifact@v4
if: always()
Expand Down Expand Up @@ -156,7 +172,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.22.5"
go-version: "1.22.0"
- shell: bash
run: |
go install gotest.tools/gotestsum@latest
Expand Down
16 changes: 12 additions & 4 deletions .mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,18 @@
"pkg/connection/connections.go":"transfer_manager/go/pkg/connection/connections.go",
"pkg/connection/resolver.go":"transfer_manager/go/pkg/connection/resolver.go",
"pkg/connection/stub_resolver.go":"transfer_manager/go/pkg/connection/stub_resolver.go",
"pkg/container/README.md":"transfer_manager/go/pkg/container/README.md",
"pkg/container/client.go":"transfer_manager/go/pkg/container/client.go",
"pkg/container/container.go":"transfer_manager/go/pkg/container/container.go",
"pkg/container/container_opts.go":"transfer_manager/go/pkg/container/container_opts.go",
"pkg/container/docker.go":"transfer_manager/go/pkg/container/docker.go",
"pkg/container/docker_mocks.go":"transfer_manager/go/pkg/container/docker_mocks.go",
"pkg/container/docker_options.go":"transfer_manager/go/pkg/container/docker_options.go",
"pkg/container/docker_test.go":"transfer_manager/go/pkg/container/docker_test.go",
"pkg/container/kubernetes.go":"transfer_manager/go/pkg/container/kubernetes.go",
"pkg/container/kubernetes_mocks.go":"transfer_manager/go/pkg/container/kubernetes_mocks.go",
"pkg/container/kubernetes_options.go":"transfer_manager/go/pkg/container/kubernetes_options.go",
"pkg/container/kubernetes_test.go":"transfer_manager/go/pkg/container/kubernetes_test.go",
"pkg/contextutil/contextutil.go":"transfer_manager/go/pkg/contextutil/contextutil.go",
"pkg/coordinator/s3coordinator/coordinator_s3.go":"transfer_manager/go/pkg/coordinator/s3coordinator/coordinator_s3.go",
"pkg/coordinator/s3coordinator/coordinator_s3_recipe.go":"transfer_manager/go/pkg/coordinator/s3coordinator/coordinator_s3_recipe.go",
Expand Down Expand Up @@ -938,10 +950,6 @@
"pkg/debezium/ydb/tests/emitter_vals_test.go":"transfer_manager/go/pkg/debezium/ydb/tests/emitter_vals_test.go",
"pkg/debezium/ydb/tests/stub.go":"transfer_manager/go/pkg/debezium/ydb/tests/stub.go",
"pkg/debezium/ydb/tests/testdata/emitter_vals_test__canon_change_item.txt":"transfer_manager/go/pkg/debezium/ydb/tests/testdata/emitter_vals_test__canon_change_item.txt",
"pkg/docker/client.go":"transfer_manager/go/pkg/docker/client.go",
"pkg/docker/docker.go":"transfer_manager/go/pkg/docker/docker.go",
"pkg/docker/docker_test.go":"transfer_manager/go/pkg/docker/docker_test.go",
"pkg/docker/mocks.go":"transfer_manager/go/pkg/docker/mocks.go",
"pkg/errors/README.md":"transfer_manager/go/pkg/errors/README.md",
"pkg/errors/categories/category.go":"transfer_manager/go/pkg/errors/categories/category.go",
"pkg/errors/categorized.go":"transfer_manager/go/pkg/errors/categorized.go",
Expand Down
22 changes: 22 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ require (
google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.29.2
k8s.io/apimachinery v0.29.2
k8s.io/client-go v0.29.2
sigs.k8s.io/yaml v1.4.0
)

Expand Down Expand Up @@ -149,6 +151,7 @@ require (
github.com/distribution/reference v0.6.0 // indirect
github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/emicklei/proto v1.11.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
Expand All @@ -160,11 +163,17 @@ require (
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.7-0.20211215081658-ee6c8cce8e87 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/flatbuffers v23.5.26+incompatible // indirect
github.com/google/gnostic v0.7.0 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/martian/v3 v3.3.3 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/tink/go v1.7.0 // indirect
Expand All @@ -180,13 +189,16 @@ require (
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-sqlite3 v1.14.24 // indirect
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
Expand All @@ -196,10 +208,15 @@ require (
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
github.com/onsi/gomega v1.34.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/paulmach/orb v0.11.1 // indirect
Expand Down Expand Up @@ -258,6 +275,11 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
)

exclude github.com/keybase/go.dbus v0.0.0-20220506165403-5aa21ea2c23a
Expand Down
Loading

0 comments on commit fd08e3c

Please sign in to comment.