diff --git a/.plano.py b/.plano.py index 2721dff..fe427c3 100644 --- a/.plano.py +++ b/.plano.py @@ -65,4 +65,4 @@ def update_plano(): """ Update the embedded Plano repo """ - update_external_from_github("external/plano-main", "ssorj", "plano") + update_external_from_github("external/plano", "ssorj", "plano") diff --git a/README.md b/README.md index 9c5f747..11a4a46 100644 --- a/README.md +++ b/README.md @@ -29,26 +29,27 @@ Add the Skewer code as a subdirectory: mkdir -p external curl -sfL https://github.com/skupperproject/skewer/archive/main.tar.gz | tar -C external -xz + mv external/skewer-main external/skewer Symlink the Skewer and Plano libraries into your `python` directory: mkdir -p python - ln -s ../external/skewer-main/python/skewer python/skewer - ln -s ../external/skewer-main/python/plano python/plano + ln -s ../external/skewer/python/skewer python/skewer + ln -s ../external/skewer/python/plano python/plano Copy the `plano` command into the root of your project: - cp external/skewer-main/plano plano + cp external/skewer/plano plano Copy the standard config files: - cp external/skewer-main/config/.plano.py .plano.py - cp external/skewer-main/config/.gitignore .gitignore + cp external/skewer/config/.plano.py .plano.py + cp external/skewer/config/.gitignore .gitignore Copy the standard workflow file: mkdir -p .github/workflows - cp external/skewer-main/config/.github/workflows/main.yaml .github/workflows/main.yaml + cp external/skewer/config/.github/workflows/main.yaml .github/workflows/main.yaml Use your editor to create a `skewer.yaml` file in the root of your project: @@ -102,6 +103,8 @@ summary: # Text to summarize what the user did (optional) next_steps: # Text linking to more examples (optional, has default text) ~~~ +To disable the GitHub workflow, set it to `null`. + A **site**: ~~~ yaml @@ -194,23 +197,26 @@ this: ~~~ yaml steps: - - standard: configure_separate_console_sessions - - standard: access_your_clusters - - standard: set_up_your_namespaces - - standard: install_skupper_in_your_namespaces - - standard: check_the_status_of_your_namespaces - - standard: link_your_namespaces + - standard: install_the_skupper_command_line_tool + - standard: set_up_your_kubeconfigs + - standard: set_up_your_kubernetes_sites + - standard: check_the_status_of_your_sites + - standard: link_your_sites + - standard: access_the_application - standard: accessing_the_web_console - standard: cleaning_up ~~~ -Note that the `link_your_namespaces` step is less generic than the -other steps (it assumes only two sites), so check that the text and -commands it produces are doing what you need. If not, you'll need to -provide a custom step. +**Note:** The `link_your_sites`, `access_the_application`, and +`cleaning_up` steps are less generic than the other steps. +`link_your_sites` assumes just two sites. `access_the_application` +assumes you have a `frontend` service. `cleaning_up` doesn't delete +any application workoads. Check that the text and commands these +steps produce are doing what you need for your example. If not, you +need to provide a custom step. -There are also some standard steps for examples based on the Skupper +There are some standard steps for examples based on the Skupper Hello World application: ~~~ yaml @@ -221,6 +227,12 @@ steps: - standard: hello_world/cleaning_up ~~~ +There is a standard step for examples that include use of Podman: + +~~~ yaml + - standard: set_up_your_podman_site +~~~ + The step commands are separated into named groups corresponding to the sites. Each named group contains a list of command entries. Each command entry has a `run` field containing a shell command and other diff --git a/example/README.md b/example/README.md index 39b2ac4..192a675 100644 --- a/example/README.md +++ b/example/README.md @@ -16,16 +16,14 @@ across cloud providers, data centers, and edge sites. * [Overview](#overview) * [Prerequisites](#prerequisites) * [Step 1: Install the Skupper command-line tool](#step-1-install-the-skupper-command-line-tool) -* [Step 2: Configure separate console sessions](#step-2-configure-separate-console-sessions) -* [Step 3: Access your clusters](#step-3-access-your-clusters) -* [Step 4: Set up your namespaces](#step-4-set-up-your-namespaces) -* [Step 5: Install Skupper in your namespaces](#step-5-install-skupper-in-your-namespaces) -* [Step 6: Check the status of your namespaces](#step-6-check-the-status-of-your-namespaces) -* [Step 7: Link your namespaces](#step-7-link-your-namespaces) -* [Step 8: Fail on demand](#step-8-fail-on-demand) -* [Step 9: Deploy the application](#step-9-deploy-the-application) -* [Step 10: Expose the backend service](#step-10-expose-the-backend-service) -* [Step 11: Test the application](#step-11-test-the-application) +* [Step 2: Set up your kubeconfigs](#step-2-set-up-your-kubeconfigs) +* [Step 3: Set up your Kubernetes sites](#step-3-set-up-your-kubernetes-sites) +* [Step 4: Check the status of your sites](#step-4-check-the-status-of-your-sites) +* [Step 5: Link your sites](#step-5-link-your-sites) +* [Step 6: Fail on demand](#step-6-fail-on-demand) +* [Step 7: Deploy the application workloads](#step-7-deploy-the-application-workloads) +* [Step 8: Expose the backend service](#step-8-expose-the-backend-service) +* [Step 9: Access the application](#step-9-access-the-application) * [Accessing the web console](#accessing-the-web-console) * [Cleaning up](#cleaning-up) * [Summary](#summary) @@ -62,7 +60,7 @@ Skupper][install-docs]. [install-script]: https://github.com/skupperproject/skupper-website/blob/main/input/install.sh [install-docs]: https://skupper.io/install/ -## Step 2: Configure separate console sessions +## Step 2: Set up your kubeconfigs Skupper is designed for use with multiple namespaces, usually on different clusters. The `skupper` and `kubectl` commands use your @@ -79,71 +77,60 @@ A single kubeconfig supports only one active context per user. Since you will be using multiple contexts at once in this exercise, you need to create distinct kubeconfigs. -Start a console session for each of your namespaces. Set the -`KUBECONFIG` environment variable to a different path in each -session. +For each namespace, open a new terminal window. In each +terminal, set the `KUBECONFIG` environment variable to a different +path and log in to your cluster. -_**Console for West:**_ +_**West:**_ ~~~ shell export KUBECONFIG=~/.kube/config-west +# Enter your provider-specific login command + ~~~ -_**Console for East:**_ +_**East:**_ ~~~ shell export KUBECONFIG=~/.kube/config-east -~~~ - -## Step 3: Access your clusters - -The procedure for accessing a Kubernetes cluster varies by -provider. [Find the instructions for your chosen -provider][kube-providers] and use them to authenticate and -configure access for each console session. - -[kube-providers]: https://skupper.io/start/kubernetes.html - -## Step 4: Set up your namespaces - -Use `kubectl create namespace` to create the namespaces you wish -to use (or use existing namespaces). Use `kubectl config -set-context` to set the current namespace for each session. +# Enter your provider-specific login command -_**Console for West:**_ - -~~~ shell -kubectl create namespace west -kubectl config set-context --current --namespace west ~~~ -_**Console for East:**_ +The login procedure varies by provider. See the documentation for +your chosen providers: -~~~ shell -kubectl create namespace east -kubectl config set-context --current --namespace east -~~~ +* [Minikube](https://skupper.io/start/minikube.html#cluster-access) +* [Amazon Elastic Kubernetes Service (EKS)](https://skupper.io/start/eks.html#cluster-access) +* [Azure Kubernetes Service (AKS)](https://skupper.io/start/aks.html#cluster-access) +* [Google Kubernetes Engine (GKE)](https://skupper.io/start/gke.html#cluster-access) +* [IBM Kubernetes Service](https://skupper.io/start/ibmks.html#cluster-access) +* [OpenShift](https://skupper.io/start/openshift.html#cluster-access) -## Step 5: Install Skupper in your namespaces +## Step 3: Set up your Kubernetes sites -The `skupper init` command installs the Skupper router and -controller in the current namespace. Run the `skupper init` command -in each namespace. +For each site, create the namespace you wish to use (or use an +existing namespace). Set the namespace on your current context. +Use `skupper init` to install Skupper in the current namespace. -**Note:** If you are using Minikube, [you need to start `minikube -tunnel`][minikube-tunnel] before you install Skupper. +**Note:** If you are using Minikube, you need to [start minikube +tunnel][minikube-tunnel] before you install Skupper. [minikube-tunnel]: https://skupper.io/start/minikube.html#running-minikube-tunnel -_**Console for West:**_ +_**West:**_ ~~~ shell +kubectl create namespace west +kubectl config set-context --current --namespace west skupper init --enable-console --enable-flow-collector ~~~ -_**Console for East:**_ +_**East:**_ ~~~ shell +kubectl create namespace east +kubectl config set-context --current --namespace east skupper init ~~~ @@ -156,19 +143,11 @@ Waiting for status... Skupper is now installed in namespace ''. Use 'skupper status' to get more information. ~~~ -## Step 6: Check the status of your namespaces +## Step 4: Check the status of your sites -Use `skupper status` in each console to check that Skupper is +Use `skupper status` in each terminal to check that Skupper is installed. -_**Console for West:**_ - -~~~ shell -skupper status -~~~ - -_**Console for East:**_ - ~~~ shell skupper status ~~~ @@ -178,33 +157,31 @@ _Sample output:_ ~~~ console $ skupper status Skupper is enabled for namespace "" in interior mode. It is connected to 1 other site. It has 1 exposed service. -The site console url is: -The credentials for internal console-auth mode are held in secret: 'skupper-console-users' ~~~ As you move through the steps below, you can use `skupper status` at any time to check your progress. -## Step 7: Link your namespaces +## Step 5: Link your sites Creating a link requires use of two `skupper` commands in conjunction, `skupper token create` and `skupper link create`. The `skupper token create` command generates a secret token that signifies permission to create a link. The token also carries the -link details. Then, in a remote namespace, The `skupper link -create` command uses the token to create a link to the namespace +link details. Then, in a remote site, The `skupper link +create` command uses the token to create a link to the site that generated it. **Note:** The link token is truly a *secret*. Anyone who has the -token can link to your namespace. Make sure that only those you -trust have access to it. +token can link to your site. Make sure that only those you trust +have access to it. -First, use `skupper token create` in one namespace to generate the -token. Then, use `skupper link create` in the other to create a -link. +First, use `skupper token create` in one site to generate the +token. Then, use `skupper link create` in another to link the two +sites. -_**Console for West:**_ +_**West:**_ ~~~ shell skupper token create ~/secret.token @@ -217,7 +194,7 @@ $ skupper token create ~/secret.token Token written to ~/secret.token ~~~ -_**Console for East:**_ +_**East:**_ ~~~ shell skupper link create ~/secret.token @@ -231,48 +208,48 @@ Site configured to link to https://10.105.193.154:8081/ed9c37f6-d78a-11ec-a8c7-0 Check the status of the link using 'skupper link status'. ~~~ -If your console sessions are on different machines, you may need +If your terminal sessions are on different machines, you may need to use `scp` or a similar tool to transfer the token securely. By default, tokens expire after a single use or 15 minutes after creation. -## Step 8: Fail on demand +## Step 6: Fail on demand -_**Console for West:**_ +_**West:**_ ~~~ shell if [ -n "${SKEWER_FAIL}" ]; then expr 1 / 0; fi ~~~ -## Step 9: Deploy the application +## Step 7: Deploy the application workloads Use `kubectl create deployment` to deploy the frontend and backend -services. +workloads. -_**Console for West:**_ +_**West:**_ ~~~ shell kubectl create deployment frontend --image quay.io/skupper/hello-world-frontend ~~~ -_**Console for East:**_ +_**East:**_ ~~~ shell kubectl create deployment backend --image quay.io/skupper/hello-world-backend --replicas 3 ~~~ -## Step 10: Expose the backend service +## Step 8: Expose the backend service -We now have two namespaces linked to form a Skupper network, but -no services are exposed on it. Skupper uses the `skupper -expose` command to select a service from one namespace for -exposure in all the linked namespaces. +We now have two sites linked to form a Skupper network, but no +services are exposed on it. Skupper uses the `skupper expose` +command to select a service from one site for exposure in all +the linked sites. Use `skupper expose` to expose the backend service on the Skupper network. -_**Console for East:**_ +_**East:**_ ~~~ shell skupper expose deployment/backend --port 8080 @@ -285,11 +262,10 @@ $ skupper expose deployment/backend --port 8080 deployment backend exposed as backend ~~~ -## Step 11: Test the application +## Step 9: Access the application -We have established connectivity between the two namespaces and -made the backend available to the frontend. Before we can test -the application, we need external access to the frontend. +In order to use and test the application, we need external access +to the frontend. Use `kubectl expose` with `--type LoadBalancer` to open network access to the frontend service. @@ -304,7 +280,7 @@ request the `/api/health` endpoint at that address. **Note:** The `` field in the following commands is a placeholder. The actual value is an IP address. -_**Console for West:**_ +_**West:**_ ~~~ shell kubectl expose deployment/frontend --port 8080 --type LoadBalancer @@ -341,7 +317,7 @@ password. following output are placeholders. The actual values are specific to your environment. -_**Console for West:**_ +_**West:**_ ~~~ shell skupper status @@ -368,7 +344,7 @@ in as user `admin` and enter the password. To remove Skupper and the other resources from this exercise, use the following commands. -_**Console for West:**_ +_**West:**_ ~~~ shell skupper delete @@ -376,7 +352,7 @@ kubectl delete service/frontend kubectl delete deployment/frontend ~~~ -_**Console for East:**_ +_**East:**_ ~~~ shell skupper delete diff --git a/example/external/skewer-main b/example/external/skewer similarity index 100% rename from example/external/skewer-main rename to example/external/skewer diff --git a/example/python/plano b/example/python/plano index a578137..431570b 120000 --- a/example/python/plano +++ b/example/python/plano @@ -1 +1 @@ -../external/skewer-main/python/plano \ No newline at end of file +../external/skewer/python/plano \ No newline at end of file diff --git a/example/python/skewer b/example/python/skewer index 6ea41b9..0cc66e2 120000 --- a/example/python/skewer +++ b/example/python/skewer @@ -1 +1 @@ -../external/skewer-main/python/skewer \ No newline at end of file +../external/skewer/python/skewer \ No newline at end of file diff --git a/example/skewer.yaml b/example/skewer.yaml index bb36722..05172a3 100644 --- a/example/skewer.yaml +++ b/example/skewer.yaml @@ -19,20 +19,18 @@ sites: KUBECONFIG: ~/.kube/config-east steps: - standard: install_the_skupper_command_line_tool - - standard: configure_separate_console_sessions - - standard: access_your_clusters - - standard: set_up_your_namespaces - - standard: install_skupper_in_your_namespaces - - standard: check_the_status_of_your_namespaces - - standard: link_your_namespaces + - standard: set_up_your_kubeconfigs + - standard: set_up_your_kubernetes_sites + - standard: check_the_status_of_your_sites + - standard: link_your_sites - title: Fail on demand commands: west: - run: | if [ -n "${SKEWER_FAIL}" ]; then expr 1 / 0; fi - - standard: hello_world/deploy_the_application + - standard: hello_world/deploy_the_application_workloads - standard: hello_world/expose_the_backend_service - - standard: hello_world/test_the_application + - standard: access_the_application - standard: accessing_the_web_console - standard: hello_world/cleaning_up summary: | diff --git a/external/plano/src/plano/_testproject/.plano.py b/external/plano/src/plano/_testproject/.plano.py index 67904b2..8cda2e7 100644 --- a/external/plano/src/plano/_testproject/.plano.py +++ b/external/plano/src/plano/_testproject/.plano.py @@ -35,7 +35,7 @@ def extended_command(alpha, beta, omega="y"): @command(parameters=[CommandParameter("message_", help="The message to print", display_name="message"), CommandParameter("count", help="Print the message COUNT times"), CommandParameter("extra", default=1, short_option="e")]) -def echo(message_, count=1, extra=None, trouble=False): +def echo(message_, count=1, extra=None, trouble=False, verbose=False): """ Print a message to the console """ diff --git a/external/plano/src/plano/_testproject/src/chucker/moretests.py b/external/plano/src/plano/_testproject/src/chucker/moretests.py new file mode 100644 index 0000000..2607880 --- /dev/null +++ b/external/plano/src/plano/_testproject/src/chucker/moretests.py @@ -0,0 +1,24 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +from plano import * + +@test +def hello_again(): + print("Hello again") diff --git a/external/plano/src/plano/_testproject/src/chucker/tests.py b/external/plano/src/plano/_testproject/src/chucker/tests.py index 144a157..4e0cec1 100644 --- a/external/plano/src/plano/_testproject/src/chucker/tests.py +++ b/external/plano/src/plano/_testproject/src/chucker/tests.py @@ -63,3 +63,8 @@ def test_widget(message): for message in "hi", "lo", "in between": add_test(f"message-{message}", test_widget, message) + +@test(disabled=True) +def badbye2(): + print("Badbye 2") + assert False diff --git a/external/plano/src/plano/_tests.py b/external/plano/src/plano/_tests.py index d9f9e6d..cf67b89 100644 --- a/external/plano/src/plano/_tests.py +++ b/external/plano/src/plano/_tests.py @@ -54,15 +54,15 @@ def archive_operations(): assert is_file("some-dir.tar.gz"), list_dir() extract_archive("some-dir.tar.gz", output_dir="some-subdir") - assert is_dir("some-subdir/some-dir") - assert is_file("some-subdir/some-dir/some-file") + assert is_dir("some-subdir/some-dir"), list_dir("some-subdir") + assert is_file("some-subdir/some-dir/some-file"), list_dir("some-subdir/some-dir") rename_archive("some-dir.tar.gz", "something-else") - assert is_file("something-else.tar.gz") + assert is_file("something-else.tar.gz"), list_dir() extract_archive("something-else.tar.gz") - assert is_dir("something-else") - assert is_file("something-else/some-file") + assert is_dir("something-else"), list_dir() + assert is_file("something-else/some-file"), list_dir("something-else") @test def command_operations(): @@ -96,6 +96,7 @@ def run(self): print("Hello") SomeCommand().main([]) + SomeCommand().main(["--verbose"]) SomeCommand().main(["--interrupt"]) with expect_system_exit(): @@ -955,6 +956,7 @@ def test_operations(): with working_module_path("src"): import chucker import chucker.tests + import chucker.moretests print_tests(chucker.tests) @@ -976,6 +978,9 @@ def test_operations(): with expect_error(): run_tests(chucker.tests, enable="*badbye*", fail_fast=True, verbose=verbose) + with expect_error(): + run_tests([chucker.tests, chucker.moretests], enable="*badbye2*", fail_fast=True, verbose=verbose) + with expect_exception(KeyboardInterrupt): run_tests(chucker.tests, enable="keyboard-interrupt", verbose=verbose) diff --git a/external/plano/src/plano/command.py b/external/plano/src/plano/command.py index 83ab041..219f964 100644 --- a/external/plano/src/plano/command.py +++ b/external/plano/src/plano/command.py @@ -260,7 +260,7 @@ def _process_commands(self): help="Print no logging to the console") for param in command.parameters.values(): - if param.name in ("verbose", "quiet"): + if not command.passthrough and param.name in ("verbose", "quiet"): continue if param.positional: @@ -322,11 +322,13 @@ def __init__(self, function): self.name = nvl(self.name, default) self.parameters = self._process_parameters(parameters) + self.passthrough = passthrough else: assert parameters is None self.name = nvl(self.name, self.parent.name) self.parameters = self.parent.parameters + self.passthrough = self.parent.passthrough doc = _inspect.getdoc(self.function) @@ -341,7 +343,6 @@ def __init__(self, function): self.help = nvl(self.help, self.parent.help) self.description = nvl(self.description, self.parent.description) - self.passthrough = passthrough self.hidden = hidden debug("Defining {}", self) diff --git a/external/plano/src/plano/github.py b/external/plano/src/plano/github.py index 044f367..8bfd9f8 100644 --- a/external/plano/src/plano/github.py +++ b/external/plano/src/plano/github.py @@ -65,9 +65,14 @@ def update_external_from_github(dir, owner, repo, ref="main"): make_parent_dir(dir) url = f"https://github.com/{owner}/{repo}/archive/{ref}.tar.gz" - name = f"{repo}-{ref}" - with working_dir(quiet=True): - http_get(url, output_file=f"{name}.tar.gz") - extract_archive(f"{name}.tar.gz") - move(name, dir, inside=False) + with temp_file() as temp: + http_get(url, output_file=temp) + + with working_dir(quiet=True): + extract_archive(temp) + + extracted_dir = list_dir()[0] + assert is_dir(extracted_dir) + + move(extracted_dir, dir, inside=False) diff --git a/external/plano/src/plano/main.py b/external/plano/src/plano/main.py index 42b8234..e0fb31c 100644 --- a/external/plano/src/plano/main.py +++ b/external/plano/src/plano/main.py @@ -74,16 +74,16 @@ class PlanoTimeout(PlanoException): ## Archive operations def make_archive(input_dir, output_file=None, quiet=False): - """ - group: archive_operations - """ - check_program("tar") archive_stem = get_base_name(input_dir) if output_file is None: - output_file = "{}.tar.gz".format(join(get_current_dir(), archive_stem)) + # tar on Windows needs this + base = join(get_current_dir(), archive_stem) + base = base.replace("\\", "/") + + output_file = f"{base}.tar.gz" _notice(quiet, "Making archive {} from directory {}", repr(output_file), repr(input_dir)) @@ -102,6 +102,9 @@ def extract_archive(input_file, output_dir=None, quiet=False): input_file = get_absolute_path(input_file) + # tar on Windows needs this + input_file = input_file.replace("\\", "/") + with working_dir(output_dir, quiet=True): run(f"tar -xf {input_file}", quiet=True) @@ -113,6 +116,9 @@ def rename_archive(input_file, new_archive_stem, quiet=False): output_dir = get_absolute_path(get_parent_dir(input_file)) output_file = "{}.tar.gz".format(join(output_dir, new_archive_stem)) + # tar on Windows needs this + output_file = output_file.replace("\\", "/") + input_file = get_absolute_path(input_file) with working_dir(quiet=True): diff --git a/python/skewer/main.py b/python/skewer/main.py index 97db7ce..dcd3bc7 100644 --- a/python/skewer/main.py +++ b/python/skewer/main.py @@ -96,7 +96,7 @@ def await_http_ok(service, url_template, user=None, password=None, timeout=240): notice(f"Waiting for HTTP OK from {url}") try: - http_get(url, insecure=insecure, user=user, password=password) + http_get(url, insecure=insecure, user=user, password=password, quiet=True) except PlanoError: if get_time() - start_time > timeout: fail(f"Timed out waiting for HTTP OK from {url}") @@ -357,7 +357,7 @@ def generate_readme_step(model, step): site = dict(model.sites)[site_name] outputs = list() - out.append(f"_**Console for {site.title}:**_") + out.append(f"_**{site.title}:**_") out.append("") out.append("~~~ shell") @@ -424,12 +424,17 @@ def apply_attribute(name, default=None): apply_attribute("preamble") apply_attribute("postamble") + platform = standard_step_data.get("platform") + if "commands" not in step.data and "commands" in standard_step_data: step.data["commands"] = dict() for i, item in enumerate(dict(model.sites).items()): site_name, site = item + if platform and site.platform != platform: + continue + if str(i) in standard_step_data["commands"]: # Is a specific index in the standard commands? commands = standard_step_data["commands"][str(i)] diff --git a/python/skewer/planocommands.py b/python/skewer/planocommands.py index c5d89d6..754fb1e 100644 --- a/python/skewer/planocommands.py +++ b/python/skewer/planocommands.py @@ -87,5 +87,5 @@ def update_skewer(): This results in local changes to review and commit. """ - update_external_from_github("external/skewer-main", "skupperproject", "skewer") - copy("external/skewer-main/config/.github/workflows/main.yaml", ".github/workflows/main.yaml") + update_external_from_github("external/skewer", "skupperproject", "skewer") + copy("external/skewer/config/.github/workflows/main.yaml", ".github/workflows/main.yaml") diff --git a/python/skewer/standardsteps.yaml b/python/skewer/standardsteps.yaml index d5dbcbf..13d2499 100644 --- a/python/skewer/standardsteps.yaml +++ b/python/skewer/standardsteps.yaml @@ -39,8 +39,9 @@ install_the_skupper_command_line_tool: [install-script]: https://github.com/skupperproject/skupper-website/blob/main/input/install.sh [install-docs]: https://skupper.io/install/ -configure_separate_console_sessions: - title: Configure separate console sessions +set_up_your_kubeconfigs: + title: Set up your kubeconfigs + platform: kubernetes preamble: | Skupper is designed for use with multiple namespaces, usually on different clusters. The `skupper` and `kubectl` commands use your @@ -57,47 +58,44 @@ configure_separate_console_sessions: Since you will be using multiple contexts at once in this exercise, you need to create distinct kubeconfigs. - Start a console session for each of your namespaces. Set the - `KUBECONFIG` environment variable to a different path in each - session. + For each namespace, open a new terminal window. In each + terminal, set the `KUBECONFIG` environment variable to a different + path and log in to your cluster. commands: "*": - - run: export KUBECONFIG=@kubeconfig@ -access_your_clusters: - title: Access your clusters - preamble: | - - The procedure for accessing a Kubernetes cluster varies by - provider. [Find the instructions for your chosen - provider][kube-providers] and use them to authenticate and - configure access for each console session. + - run: | + export KUBECONFIG=@kubeconfig@ + # Enter your provider-specific login command + postamble: | + The login procedure varies by provider. See the documentation for + your chosen providers: - [kube-providers]: https://skupper.io/start/kubernetes.html -set_up_your_namespaces: - title: Set up your namespaces - preamble: | - Use `kubectl create namespace` to create the namespaces you wish - to use (or use existing namespaces). Use `kubectl config - set-context` to set the current namespace for each session. - commands: - "*": - - run: kubectl create namespace @namespace@ - - run: kubectl config set-context --current --namespace @namespace@ -install_skupper_in_your_namespaces: - title: Install Skupper in your namespaces + * [Minikube](https://skupper.io/start/minikube.html#cluster-access) + * [Amazon Elastic Kubernetes Service (EKS)](https://skupper.io/start/eks.html#cluster-access) + * [Azure Kubernetes Service (AKS)](https://skupper.io/start/aks.html#cluster-access) + * [Google Kubernetes Engine (GKE)](https://skupper.io/start/gke.html#cluster-access) + * [IBM Kubernetes Service](https://skupper.io/start/ibmks.html#cluster-access) + * [OpenShift](https://skupper.io/start/openshift.html#cluster-access) +set_up_your_kubernetes_sites: + title: Set up your Kubernetes sites + platform: kubernetes preamble: | - The `skupper init` command installs the Skupper router and - controller in the current namespace. Run the `skupper init` command - in each namespace. + For each site, create the namespace you wish to use (or use an + existing namespace). Set the namespace on your current context. + Use `skupper init` to install Skupper in the current namespace. - **Note:** If you are using Minikube, [you need to start `minikube - tunnel`][minikube-tunnel] before you install Skupper. + **Note:** If you are using Minikube, you need to [start minikube + tunnel][minikube-tunnel] before you install Skupper. [minikube-tunnel]: https://skupper.io/start/minikube.html#running-minikube-tunnel commands: "0": + - run: kubectl create namespace @namespace@ + - run: kubectl config set-context --current --namespace @namespace@ - run: skupper init --enable-console --enable-flow-collector "*": + - run: kubectl create namespace @namespace@ + - run: kubectl config set-context --current --namespace @namespace@ - run: skupper init postamble: | _Sample output:_ @@ -108,45 +106,78 @@ install_skupper_in_your_namespaces: Waiting for status... Skupper is now installed in namespace ''. Use 'skupper status' to get more information. ~~~ -check_the_status_of_your_namespaces: - title: Check the status of your namespaces +set_up_your_podman_site: + title: Set up your Podman site + platform: podman preamble: | - Use `skupper status` in each console to check that Skupper is - installed. + Open a new terminal window and set the `SKUPPER_PLATFORM` + environment variable to `podman`. + + Make sure the Podman API service is available. On most systems + you can use: + + ~~~ + systemctl --user enable --now podman.socket + ~~~ + + You can also use: + + ~~~ + podman system service --time=0 unix://$XDG_RUNTIME_DIR/podman/podman.sock & + ~~~ + + Then use `skupper init` to install Skupper in your Podman environment. commands: "*": - - run: skupper status + - run: export SKUPPER_PLATFORM=podman + - run: systemctl --user enable --now podman.socket + # - run: podman system service --time=0 unix://$XDG_RUNTIME_DIR/podman/podman.sock & + - run: skupper init --ingress none postamble: | _Sample output:_ + ~~~ console + $ skupper init --ingress none + Skupper is now installed for user 'jross'. Use 'skupper status' to get more information. + ~~~ +check_the_status_of_your_sites: + title: Check the status of your sites + preamble: | + Use `skupper status` in each terminal to check that Skupper is + installed. + + ~~~ shell + skupper status + ~~~ + + _Sample output:_ + ~~~ console $ skupper status Skupper is enabled for namespace "" in interior mode. It is connected to 1 other site. It has 1 exposed service. - The site console url is: - The credentials for internal console-auth mode are held in secret: 'skupper-console-users' ~~~ As you move through the steps below, you can use `skupper status` at any time to check your progress. -link_your_namespaces: - title: Link your namespaces +link_your_sites: + title: Link your sites preamble: | Creating a link requires use of two `skupper` commands in conjunction, `skupper token create` and `skupper link create`. The `skupper token create` command generates a secret token that signifies permission to create a link. The token also carries the - link details. Then, in a remote namespace, The `skupper link - create` command uses the token to create a link to the namespace + link details. Then, in a remote site, The `skupper link + create` command uses the token to create a link to the site that generated it. **Note:** The link token is truly a *secret*. Anyone who has the - token can link to your namespace. Make sure that only those you - trust have access to it. + token can link to your site. Make sure that only those you trust + have access to it. - First, use `skupper token create` in one namespace to generate the - token. Then, use `skupper link create` in the other to create a - link. + First, use `skupper token create` in one site to generate the + token. Then, use `skupper link create` in another to link the two + sites. commands: "0": - run: skupper token create ~/secret.token @@ -159,10 +190,45 @@ link_your_namespaces: - run: skupper link status --wait 60 apply: test postamble: | - If your console sessions are on different machines, you may need + If your terminal sessions are on different machines, you may need to use `scp` or a similar tool to transfer the token securely. By default, tokens expire after a single use or 15 minutes after creation. +access_the_application: + title: Access the application + preamble: | + In order to use and test the application, we need external access + to the frontend. + + Use `kubectl expose` with `--type LoadBalancer` to open network + access to the frontend service. + + Once the frontend is exposed, use `kubectl get service/frontend` + to look up the external IP of the frontend service. If the + external IP is ``, try again after a moment. + + Once you have the external IP, use `curl` or a similar tool to + request the `/api/health` endpoint at that address. + + **Note:** The `` field in the following commands is a + placeholder. The actual value is an IP address. + commands: + "0": + - run: kubectl expose deployment/frontend --port 8080 --type LoadBalancer + output: service/frontend exposed + - await_resource: service/frontend + - run: kubectl get service/frontend + apply: readme + output: | + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + frontend LoadBalancer 10.103.232.28 8080:30407/TCP 15s + - run: curl http://:8080/api/health + apply: readme + output: OK + - await_http_ok: [service/frontend, "http://{}:8080/api/health"] + postamble: | + If everything is in order, you can now access the web interface by + navigating to `http://:8080/` in your browser. accessing_the_web_console: title: Accessing the web console numbered: false @@ -200,11 +266,11 @@ cleaning_up: commands: "*": - run: skupper delete -hello_world/deploy_the_application: - title: Deploy the application +hello_world/deploy_the_application_workloads: + title: Deploy the application workloads preamble: | Use `kubectl create deployment` to deploy the frontend and backend - services. + workloads. commands: "0": - run: kubectl create deployment frontend --image quay.io/skupper/hello-world-frontend @@ -213,10 +279,10 @@ hello_world/deploy_the_application: hello_world/expose_the_backend_service: title: Expose the backend service preamble: | - We now have two namespaces linked to form a Skupper network, but - no services are exposed on it. Skupper uses the `skupper - expose` command to select a service from one namespace for - exposure in all the linked namespaces. + We now have two sites linked to form a Skupper network, but no + services are exposed on it. Skupper uses the `skupper expose` + command to select a service from one site for exposure in all + the linked sites. Use `skupper expose` to expose the backend service on the Skupper network. @@ -225,42 +291,6 @@ hello_world/expose_the_backend_service: - await_resource: deployment/backend - run: skupper expose deployment/backend --port 8080 output: deployment backend exposed as backend -hello_world/test_the_application: - title: Test the application - preamble: | - We have established connectivity between the two namespaces and - made the backend available to the frontend. Before we can test - the application, we need external access to the frontend. - - Use `kubectl expose` with `--type LoadBalancer` to open network - access to the frontend service. - - Once the frontend is exposed, use `kubectl get service/frontend` - to look up the external IP of the frontend service. If the - external IP is ``, try again after a moment. - - Once you have the external IP, use `curl` or a similar tool to - request the `/api/health` endpoint at that address. - - **Note:** The `` field in the following commands is a - placeholder. The actual value is an IP address. - commands: - "0": - - run: kubectl expose deployment/frontend --port 8080 --type LoadBalancer - output: service/frontend exposed - - await_resource: service/frontend - - run: kubectl get service/frontend - apply: readme - output: | - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - frontend LoadBalancer 10.103.232.28 8080:30407/TCP 15s - - run: curl http://:8080/api/health - apply: readme - output: OK - - await_http_ok: [service/frontend, "http://{}:8080/api/health"] - postamble: | - If everything is in order, you can now access the web interface by - navigating to `http://:8080/` in your browser. hello_world/cleaning_up: name: cleaning_up title: Cleaning up