Skip to content

Commit 3bde83b

Browse files
authored
Merge branch 'main' into minimun-iaas-service-versions
2 parents 9a51b2f + 8c383ca commit 3bde83b

File tree

12 files changed

+443
-38
lines changed

12 files changed

+443
-38
lines changed

Tests/config.toml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,51 @@ subjects = [
3434
workers = 4
3535

3636

37+
[presets.kaas-dev]
38+
scopes = [
39+
"scs-compatible-kaas",
40+
]
41+
subjects = [
42+
"kind-current",
43+
"kind-current-1",
44+
"kind-current-2",
45+
]
46+
workers = 1 # better restrict this with clusters running on local machine
47+
48+
3749
[scopes.scs-compatible-iaas]
3850
spec = "./scs-compatible-iaas.yaml"
3951

4052

53+
[scopes.scs-compatible-kaas]
54+
spec = "./scs-compatible-kaas.yaml"
55+
56+
4157
# default subject (not a real subject, but used to declare a default mapping)
4258
# (this is the only mapping declaration that supports using Python string interpolation)
4359
[subjects._.mapping]
4460
os_cloud = "{subject}"
61+
subject_root = "{subject}"
62+
63+
64+
[subjects._.kubernetes_setup]
65+
clusterspec = "kaas/clusterspec.yaml"
66+
67+
68+
[subjects.kind-current.kubernetes_setup]
69+
kube_plugin = "kind"
70+
kube_plugin_config = "kaas/kind_config.yaml"
71+
clusterspec_cluster = "current-k8s-release"
72+
73+
74+
[subjects.kind-current-1.kubernetes_setup]
75+
kube_plugin = "kind"
76+
kube_plugin_config = "kaas/kind_config.yaml"
77+
clusterspec_cluster = "current-k8s-release-1"
78+
79+
80+
[subjects.kind-current-2.kubernetes_setup]
81+
kube_plugin = "kind"
82+
kube_plugin_config = "kaas/kind_config.yaml"
83+
clusterspec_cluster = "current-k8s-release-2"
84+

Tests/kaas/clusterspec.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# this file specifies all clusters that have to be provisioned for the tests to run
2+
clusters:
3+
current-k8s-release:
4+
branch: "1.31"
5+
kubeconfig: kubeconfig.yaml
6+
current-k8s-release-1:
7+
branch: "1.30"
8+
kubeconfig: kubeconfig.yaml
9+
current-k8s-release-2:
10+
branch: "1.29"
11+
kubeconfig: kubeconfig.yaml

Tests/kaas/kind_config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: Cluster
2+
apiVersion: kind.x-k8s.io/v1alpha4
3+
nodes:
4+
- role: control-plane
5+
- role: worker

Tests/kaas/plugin/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Plugin for provisioning k8s clusters and performing conformance tests on these clusters
2+
3+
## Development environment
4+
5+
### requirements
6+
7+
* [docker](https://docs.docker.com/engine/install/)
8+
* [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
9+
10+
### setup for development
11+
12+
1. Generate python 3.10 env
13+
14+
```bash
15+
sudo apt-get install python3.10-dev
16+
virtualenv -p /usr/bin/python3.10 venv
17+
echo "*" >> venv/.gitignore
18+
source venv/bin/activate
19+
(venv) curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10
20+
(venv) python3.10 -m pip install --upgrade pip
21+
(venv) python3.10 -m pip --version
22+
23+
```
24+
25+
2. Install dependencies:
26+
27+
```bash
28+
(venv) pip install pip-tools
29+
(venv) pip-compile requirements.in
30+
(venv) pip-sync requirements.txt
31+
```
32+
33+
3. Set environment variables and launch the process:
34+
35+
```bash
36+
(venv) export CLUSTER_PROVIDER="kind"
37+
(venv) python run.py
38+
```

Tests/kaas/plugin/interface.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
3+
class KubernetesClusterPlugin():
4+
"""
5+
An abstract base class for custom Kubernetes cluster provider plugins.
6+
It represents an interface class from which the api provider-specific
7+
plugins must be derived as child classes
8+
9+
To implement fill the methods `create_cluster` and `delete_cluster` with
10+
api provider-specific functionalities for creating and deleting clusters.
11+
The `create_cluster` method must ensure that the kubeconfigfile is provided
12+
at the position in the file system defined by the parameter
13+
`kubeconfig_filepath`
14+
15+
- Implement `create_cluster` and `delete_cluster` methods
16+
- Create `__init__(self, config_file)` method to handle api specific
17+
configurations.
18+
19+
Example:
20+
.. code:: python
21+
22+
from interface import KubernetesClusterPlugin
23+
from apiX_library import cluster_api_class as ClusterAPI
24+
25+
class PluginX(KubernetesClusterPlugin):
26+
27+
def __init__(self, config_file):
28+
self.config = config_file
29+
30+
def create_cluster(self, cluster_name, version, kubeconfig_filepath):
31+
self.cluster = ClusterAPI(name=cluster_name, image=cluster_image, kubeconfig_filepath)
32+
self.cluster.create(self.config)
33+
34+
def delete_cluster(self, cluster_name):
35+
self.cluster = ClusterAPI(cluster_name)
36+
self.cluster.delete()
37+
..
38+
"""
39+
40+
def create_cluster(self, cluster_name, version, kubeconfig_filepath):
41+
"""
42+
This method is to be called to create a k8s cluster
43+
:param: cluster_name:
44+
:param: version:
45+
:param: kubeconfig_filepath:
46+
"""
47+
raise NotImplementedError
48+
49+
def delete_cluster(self, cluster_name):
50+
"""
51+
This method is to be called in order to unprovision a cluster
52+
:param: cluster_name:
53+
"""
54+
raise NotImplementedError

Tests/kaas/plugin/plugin_kind.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import logging
2+
import os
3+
import os.path
4+
from pathlib import Path
5+
6+
from interface import KubernetesClusterPlugin
7+
from pytest_kind import KindCluster
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
class PluginKind(KubernetesClusterPlugin):
13+
"""
14+
Plugin to handle the provisioning of kubernetes cluster for
15+
conformance testing purpose with the use of Kind
16+
"""
17+
def __init__(self, config_path):
18+
logger.info("Init PluginKind")
19+
self.config = config_path
20+
logger.debug(self.config)
21+
self.working_directory = os.getcwd()
22+
logger.debug(f"Working from {self.working_directory}")
23+
24+
def create_cluster(self, cluster_name, version, kubeconfig):
25+
"""
26+
This method is to be called to create a k8s cluster
27+
:param: kubernetes_version:
28+
:return: kubeconfig_filepath
29+
"""
30+
cluster_version = version
31+
if cluster_version == '1.29':
32+
cluster_version = 'v1.29.8'
33+
elif cluster_version == '1.30':
34+
cluster_version = 'v1.30.4'
35+
elif cluster_version == '1.31' or cluster_version == 'default':
36+
cluster_version = 'v1.31.1'
37+
cluster_image = f"kindest/node:{cluster_version}"
38+
kubeconfig_filepath = Path(kubeconfig)
39+
if kubeconfig_filepath is None:
40+
raise ValueError("kubeconfig_filepath is missing")
41+
else:
42+
self.cluster = KindCluster(name=cluster_name, image=cluster_image, kubeconfig=kubeconfig_filepath)
43+
if self.config is None:
44+
self.cluster.create()
45+
else:
46+
self.cluster.create(self.config)
47+
48+
def delete_cluster(self, cluster_name):
49+
self.cluster = KindCluster(cluster_name)
50+
self.cluster.delete()

Tests/kaas/plugin/plugin_static.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import shutil
2+
3+
from interface import KubernetesClusterPlugin
4+
5+
6+
class PluginStatic(KubernetesClusterPlugin):
7+
"""
8+
Plugin to handle the provisioning of kubernetes
9+
using a kubeconfig file
10+
"""
11+
12+
def __init__(self, config_path):
13+
self.kubeconfig_path = config_path
14+
15+
def create_cluster(self, cluster_name, version, kubeconfig):
16+
shutil.copyfile(self.kubeconfig_path, kubeconfig)
17+
18+
def delete_cluster(self, cluster_name, version):
19+
pass

Tests/kaas/plugin/requirements.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pytest-kind
2+
kubernetes

Tests/kaas/plugin/requirements.txt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.12
3+
# by the following command:
4+
#
5+
# pip-compile requirements.in
6+
#
7+
cachetools==5.5.0
8+
# via google-auth
9+
certifi==2024.8.30
10+
# via
11+
# kubernetes
12+
# requests
13+
charset-normalizer==3.3.2
14+
# via requests
15+
google-auth==2.34.0
16+
# via kubernetes
17+
idna==3.8
18+
# via requests
19+
kubernetes==30.1.0
20+
# via -r requirements.in
21+
oauthlib==3.2.2
22+
# via
23+
# kubernetes
24+
# requests-oauthlib
25+
pyasn1==0.6.0
26+
# via
27+
# pyasn1-modules
28+
# rsa
29+
pyasn1-modules==0.4.0
30+
# via google-auth
31+
pykube-ng==23.6.0
32+
# via pytest-kind
33+
pytest-kind==22.11.1
34+
# via -r requirements.in
35+
python-dateutil==2.9.0.post0
36+
# via kubernetes
37+
pyyaml==6.0.2
38+
# via
39+
# kubernetes
40+
# pykube-ng
41+
requests==2.32.3
42+
# via
43+
# kubernetes
44+
# pykube-ng
45+
# requests-oauthlib
46+
requests-oauthlib==2.0.0
47+
# via kubernetes
48+
rsa==4.9
49+
# via google-auth
50+
six==1.16.0
51+
# via
52+
# kubernetes
53+
# python-dateutil
54+
urllib3==2.2.2
55+
# via
56+
# kubernetes
57+
# pykube-ng
58+
# requests
59+
websocket-client==1.8.0
60+
# via kubernetes

Tests/kaas/plugin/run_plugin.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env python3
2+
import logging
3+
import os.path
4+
5+
import click
6+
import yaml
7+
8+
from plugin_kind import PluginKind
9+
from plugin_static import PluginStatic
10+
11+
PLUGIN_LOOKUP = {
12+
"kind": PluginKind,
13+
"static": PluginStatic,
14+
}
15+
16+
17+
def init_plugin(plugin_kind, config_path):
18+
plugin_maker = PLUGIN_LOOKUP.get(plugin_kind)
19+
if plugin_maker is None:
20+
raise ValueError(f"unknown plugin '{plugin_kind}'")
21+
return plugin_maker(config_path)
22+
23+
24+
def load_spec(clusterspec_path):
25+
with open(clusterspec_path, "rb") as fileobj:
26+
return yaml.load(fileobj, Loader=yaml.SafeLoader)
27+
28+
29+
@click.group()
30+
def cli():
31+
pass
32+
33+
34+
@cli.command()
35+
@click.argument('plugin_kind', type=click.Choice(list(PLUGIN_LOOKUP), case_sensitive=False))
36+
@click.argument('plugin_config', type=click.Path(exists=True, dir_okay=False))
37+
@click.argument('clusterspec_path', type=click.Path(exists=True, dir_okay=False))
38+
@click.argument('cluster_id', type=str, default="default")
39+
def create(plugin_kind, plugin_config, clusterspec_path, cluster_id):
40+
clusterspec = load_spec(clusterspec_path)['clusters']
41+
plugin = init_plugin(plugin_kind, plugin_config)
42+
clusterinfo = clusterspec[cluster_id]
43+
plugin.create_cluster(cluster_id, clusterinfo['branch'], os.path.abspath(clusterinfo['kubeconfig']))
44+
45+
46+
@cli.command()
47+
@click.argument('plugin_kind', type=click.Choice(list(PLUGIN_LOOKUP), case_sensitive=False))
48+
@click.argument('plugin_config', type=click.Path(exists=True, dir_okay=False))
49+
@click.argument('clusterspec_path', type=click.Path(exists=True, dir_okay=False))
50+
@click.argument('cluster_id', type=str, default="default")
51+
def delete(plugin_kind, plugin_config, clusterspec_path, cluster_id):
52+
plugin = init_plugin(plugin_kind, plugin_config)
53+
plugin.delete_cluster(cluster_id)
54+
55+
56+
if __name__ == '__main__':
57+
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
58+
cli()

0 commit comments

Comments
 (0)