From ef35ace65a937ef9053b7cdc120bae544f9c5ea5 Mon Sep 17 00:00:00 2001
From: msimonin <matthieu.simonin@inria.fr>
Date: Mon, 30 Nov 2020 15:48:24 +0100
Subject: [PATCH] Service: new service K3s

We had swarm, we know have a k3 cluster.
We also have a Dask cluster but this is another story.
---
 docs/apidoc/examples/k3s.py     | 30 +++++++++++++++++
 docs/apidoc/service.rst         | 10 ++++++
 docs/conf.py                    |  1 +
 enoslib/__init__.py             |  1 +
 enoslib/service/k3s/__init__.py |  0
 enoslib/service/k3s/k3s.py      | 57 +++++++++++++++++++++++++++++++++
 6 files changed, 99 insertions(+)
 create mode 100644 docs/apidoc/examples/k3s.py
 create mode 100644 enoslib/service/k3s/__init__.py
 create mode 100644 enoslib/service/k3s/k3s.py

diff --git a/docs/apidoc/examples/k3s.py b/docs/apidoc/examples/k3s.py
new file mode 100644
index 00000000..dbd261bf
--- /dev/null
+++ b/docs/apidoc/examples/k3s.py
@@ -0,0 +1,30 @@
+import logging
+
+from enoslib import *
+
+
+logging.basicConfig(level=logging.INFO)
+
+# claim the resources
+network = G5kNetworkConf(id="n1", type="prod", roles=["my_network"], site="rennes")
+
+conf = (
+    G5kConf.from_settings(job_type="allow_classic_ssh", job_name="k3s")
+    .add_network_conf(network)
+    .add_machine(
+        roles=["master"], cluster="paravance", nodes=1, primary_network=network
+    )
+    .add_machine(
+        roles=["agent"], cluster="parapluie", nodes=10, primary_network=network
+    )
+    .finalize()
+)
+
+
+provider = G5k(conf)
+# Get actual resources
+roles, networks = provider.init()
+
+
+k3s = K3s(master=roles["master"], agent=roles["agent"])
+k3s.deploy()
diff --git a/docs/apidoc/service.rst b/docs/apidoc/service.rst
index f6b08d24..42da915d 100644
--- a/docs/apidoc/service.rst
+++ b/docs/apidoc/service.rst
@@ -39,6 +39,16 @@ Dstat Service Class
 .. automodule:: enoslib.service.dstat.dstat
     :members: Dstat
 
+K3s (container orchestration)
+=============================
+
+K3s Service Class
+--------------------
+
+
+.. automodule:: enoslib.service.k3s.k3s
+    :members: K3s
+
 Locust (Load generation)
 ========================
 
diff --git a/docs/conf.py b/docs/conf.py
index 7025de01..320b5b4c 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -173,6 +173,7 @@ texinfo_documents = [
 
 rst_epilog = """
 .. |enoslib| replace:: EnOSlib
+.. |chat| replace:: https://framateam.org/enoslib/channels/town-square
 """
 
 # Document also the __init__
diff --git a/enoslib/__init__.py b/enoslib/__init__.py
index 2642424d..caf42b1a 100644
--- a/enoslib/__init__.py
+++ b/enoslib/__init__.py
@@ -18,6 +18,7 @@ from enoslib.service.conda.conda import Conda, conda_play_on, conda_run_command,
 from enoslib.service.docker.docker import Docker
 from enoslib.service.dstat.dstat import Dstat
 from enoslib.service.locust.locust import Locust
+from enoslib.service.k3s.k3s import K3s
 from enoslib.service.monitoring.monitoring import Monitoring
 from enoslib.service.netem.netem import Netem, SimpleNetem
 from enoslib.service.skydive.skydive import Skydive
diff --git a/enoslib/service/k3s/__init__.py b/enoslib/service/k3s/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/enoslib/service/k3s/k3s.py b/enoslib/service/k3s/k3s.py
new file mode 100644
index 00000000..fb101e13
--- /dev/null
+++ b/enoslib/service/k3s/k3s.py
@@ -0,0 +1,57 @@
+from enoslib.api import play_on, run_command
+from typing import List
+
+from ..service import Service
+from enoslib.types import Host
+
+
+class K3s(Service):
+    def __init__(self, master: List[Host], agent: List[Host]):
+        """Deploy a K3s cluster.
+
+        Reference:
+        https://rancher.com/docs/k3s/latest/en/quick-start/
+
+        This is a basic setup for now. Let us know if something is needed here:
+        |chat|
+
+        For instance
+
+        - automatic deployment of the dashboard
+        - private registry configuration (e.g G5k registry)
+        - ...
+
+        Examples:
+
+            .. literalinclude:: examples/k3s.py
+                :language: python
+                :linenos:
+        """
+        self.master = master
+        self.agent = agent
+        self.roles = dict(master=self.master, agent=self.agent)
+
+    def deploy(self):
+        with play_on(roles=self.roles) as p:
+            p.apt(name="curl", state="present")
+
+        with play_on(pattern_hosts="master", roles=self.roles, gather_facts=False) as p:
+            p.shell("curl -sfL https://get.k3s.io | sh")
+        # Getting the token
+        result = run_command(
+            "cat /var/lib/rancher/k3s/server/node-token",
+            pattern_hosts="master",
+            roles=self.roles,
+        )
+        token = result["ok"][self.master[0].alias]["stdout"]
+        with play_on(pattern_hosts="agent", roles=self.roles, gather_facts=False) as p:
+            p.shell((
+                f"curl -sfL https://get.k3s.io |"
+                f"K3S_URL=https://{self.master[0].address}:6443 K3S_TOKEN={token} sh"
+            ))
+
+    def destroy():
+        pass
+
+    def backup():
+        pass
-- 
GitLab