Skip to content

Commit

Permalink
Skewer update
Browse files Browse the repository at this point in the history
  • Loading branch information
ssorj committed Feb 6, 2024
1 parent f427f10 commit 48efc27
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 34 deletions.
8 changes: 4 additions & 4 deletions external/skewer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ used only for testing and do not impact the README.
~~~ yaml
- await_resource: # A resource for which to await readiness (optional)
# Example: await_resource: deployment/frontend
- await_external_ip: # A service for which to await an external IP (optional)
# Example: await_service: service/frontend
- await_ingress: # A service for which to await an external hostname or IP (optional)
# Example: await_ingress: service/frontend
- await_http_ok: # A service and URL template for which to await an HTTP OK response (optional)
# Example: await_http_ok: [service/frontend, "http://{}:8080/api/hello"]
~~~
Expand All @@ -268,9 +268,9 @@ Example commands:
~~~ yaml
commands:
east:
- run: kubectl expose deployment/backend --port 8080 --type LoadBalancer
- run: skupper expose deployment/backend --port 8080
output: |
service/frontend exposed
deployment backend exposed as backend
west:
- await_resource: service/backend
- run: kubectl get service/backend
Expand Down
30 changes: 27 additions & 3 deletions external/skewer/external/plano/src/plano/_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,30 @@ def file_operations():
result = get_file_size(file)
assert result == 10, result

zeta_dir = make_dir("zeta-dir")
zeta_file = touch(join(zeta_dir, "zeta-file"))

eta_dir = make_dir("eta-dir")
eta_file = touch(join(eta_dir, "eta-file"))

replace(zeta_dir, eta_dir)
assert not exists(zeta_file)
assert exists(zeta_dir)
assert is_file(join(zeta_dir, "eta-file"))

with expect_exception():
replace(zeta_dir, "not-there")

assert exists(zeta_dir)
assert is_file(join(zeta_dir, "eta-file"))

theta_file = write("theta-file", "theta")
iota_file = write("iota-file", "iota")

replace(theta_file, iota_file)
assert not exists(iota_file)
assert read(theta_file) == "iota"

@test
def github_operations():
result = convert_github_markdown("# Hello, Fritz")
Expand Down Expand Up @@ -479,7 +503,7 @@ def io_operations():
assert is_file(file_c), file_c

file_d = write("d", "front@middle@@middle@back")
path = replace_in_file(file_d, "@middle@", "M", count=1)
path = string_replace_file(file_d, "@middle@", "M", count=1)
result = read(path)
assert result == "frontM@middle@back", result

Expand Down Expand Up @@ -837,10 +861,10 @@ def process_operations():

@test
def string_operations():
result = replace("ab", "a", "b")
result = string_replace("ab", "a", "b")
assert result == "bb", result

result = replace("aba", "a", "b", count=1)
result = string_replace("aba", "a", "b", count=1)
assert result == "bba", result

result = remove_prefix(None, "xxx")
Expand Down
6 changes: 4 additions & 2 deletions external/skewer/external/plano/src/plano/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def convert_github_markdown(markdown):
content = http_post("https://api.github.com/markdown", json, content_type="application/json")

# Remove the "user-content-" prefix from internal anchors
content = replace(content, "id=\"user-content-", "id=\"")
content = content.replace("id=\"user-content-", "id=\"")

return _html_template.replace("@content@", content)

Expand All @@ -67,6 +67,8 @@ def update_external_from_github(dir, owner, repo, ref="main"):
url = f"https://github.com/{owner}/{repo}/archive/{ref}.tar.gz"

with temp_file() as temp:
assert exists(temp)

http_get(url, output_file=temp)

with working_dir(quiet=True):
Expand All @@ -75,4 +77,4 @@ def update_external_from_github(dir, owner, repo, ref="main"):
extracted_dir = list_dir()[0]
assert is_dir(extracted_dir)

move(extracted_dir, dir, inside=False)
replace(dir, extracted_dir)
36 changes: 33 additions & 3 deletions external/skewer/external/plano/src/plano/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,36 @@ def move(from_path, to_path, inside=True, quiet=False):

return to_path

def replace(path, replacement, quiet=False):
path = expand(path)
replacement = expand(replacement)

_notice(quiet, "Replacing {} with {}", repr(path), repr(replacement))

with temp_dir() as backup_dir:
backup = join(backup_dir, "backup")
backup_created = False

if exists(path):
move(path, backup, quiet=True)
backup_created = True

try:
move(replacement, path, quiet=True)
except OSError:
notice("Removing")
remove(path, quiet=True)

if backup_created:
move(backup, path, quiet=True)

raise

assert not exists(replacement), replacement
assert exists(path), path

return path

def remove(paths, quiet=False):
if is_string(paths):
paths = (paths,)
Expand Down Expand Up @@ -649,9 +679,9 @@ def tail_lines(file, count):

return lines[-count:]

def replace_in_file(file, expr, replacement, count=0):
def string_replace_file(file, expr, replacement, count=0):
file = expand(file)
return write(file, replace(read(file), expr, replacement, count=count))
return write(file, string_replace(read(file), expr, replacement, count=count))

def concatenate(file, input_files):
file = expand(file)
Expand Down Expand Up @@ -1387,7 +1417,7 @@ def _default_sigterm_handler(signum, frame):

## String operations

def replace(string, expr, replacement, count=0):
def string_replace(string, expr, replacement, count=0):
return _re.sub(expr, replacement, string, count)

def remove_prefix(string, prefix):
Expand Down
56 changes: 34 additions & 22 deletions external/skewer/python/skewer/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ def check_environment():
def resource_exists(resource):
return run(f"kubectl get {resource}", output=DEVNULL, check=False, quiet=True).exit_code == 0

def get_resource_jsonpath(resource, jsonpath):
def get_resource_json(resource, jsonpath=""):
return call(f"kubectl get {resource} -o jsonpath='{{{jsonpath}}}'", quiet=True)

def await_resource(resource, timeout=240):
def await_resource(resource, timeout=300):
assert "/" in resource, resource

start_time = get_time()
Expand All @@ -63,32 +63,44 @@ def await_resource(resource, timeout=240):
run(f"kubectl logs {resource}")
raise

def await_external_ip(service, timeout=240):
def await_ingress(service, timeout=300):
assert service.startswith("service/"), service

start_time = get_time()

await_resource(service, timeout=timeout)

while True:
notice(f"Waiting for external IP from {service} to become available")
notice(f"Waiting for hostname or IP from {service} to become available")

if get_resource_jsonpath(service, ".status.loadBalancer.ingress") != "":
json = get_resource_json(service, ".status.loadBalancer.ingress")

if json != "":
break

if get_time() - start_time > timeout:
fail(f"Timed out waiting for external IP for {service}")
fail(f"Timed out waiting for hostnmae or external IP for {service}")

sleep(5, quiet=True)

return get_resource_jsonpath(service, ".status.loadBalancer.ingress[0].ip")
data = parse_json(json)

if len(data):
if "hostname" in data[0]:
return data[0]["hostname"]

if "ip" in data[0]:
return data[0]["ip"]

def await_http_ok(service, url_template, user=None, password=None, timeout=240):
fail(f"Failed to get hostname or IP from {service}")

def await_http_ok(service, url_template, user=None, password=None, timeout=300):
assert service.startswith("service/"), service

start_time = get_time()

ip = await_external_ip(service, timeout=timeout)
ip = await_ingress(service, timeout=timeout)

url = url_template.format(ip)
insecure = url.startswith("https")

Expand All @@ -108,7 +120,7 @@ def await_http_ok(service, url_template, user=None, password=None, timeout=240):
def await_console_ok():
await_resource("secret/skupper-console-users")

password = get_resource_jsonpath("secret/skupper-console-users", ".data.admin")
password = get_resource_json("secret/skupper-console-users", ".data.admin")
password = base64_decode(password)

await_http_ok("service/skupper", "https://{}:8010/", user="admin", password=password)
Expand Down Expand Up @@ -164,8 +176,8 @@ def run_step(model, step, work_dir, check=True):
if command.await_resource:
await_resource(command.await_resource)

if command.await_external_ip:
await_external_ip(command.await_external_ip)
if command.await_ingress:
await_ingress(command.await_ingress)

if command.await_http_ok:
await_http_ok(*command.await_http_ok)
Expand All @@ -187,16 +199,16 @@ def pause_for_demo(model):
if first_site.platform == "kubernetes":
with first_site:
if resource_exists("service/frontend"):
if get_resource_jsonpath("service/frontend", ".spec.type") == "LoadBalancer":
frontend_ip = await_external_ip("service/frontend")
frontend_url = f"http://{frontend_ip}:8080/"
if get_resource_json("service/frontend", ".spec.type") == "LoadBalancer":
frontend_host = await_ingress("service/frontend")
frontend_url = f"http://{frontend_host}:8080/"

if resource_exists("secret/skupper-console-users"):
console_ip = await_external_ip("service/skupper")
console_url = f"https://{console_ip}:8010/"
console_host = await_ingress("service/skupper")
console_url = f"https://{console_host}:8010/"

await_resource("secret/skupper-console-users")
password = get_resource_jsonpath("secret/skupper-console-users", ".data.admin")
password = get_resource_json("secret/skupper-console-users", ".data.admin")
password = base64_decode(password).decode("ascii")

print()
Expand Down Expand Up @@ -284,9 +296,9 @@ def append_toc_entry(heading, condition=True):
if not condition:
return

fragment = replace(heading, r"[ -]", "_")
fragment = replace(fragment, r"[\W]", "")
fragment = replace(fragment, "_", "-")
fragment = string_replace(heading, r"[ -]", "_")
fragment = string_replace(fragment, r"[\W]", "")
fragment = string_replace(fragment, "_", "-")
fragment = fragment.lower()

out.append(f"* [{heading}](#{fragment})")
Expand Down Expand Up @@ -651,7 +663,7 @@ class Command:
apply = object_property("apply")
output = object_property("output")
await_resource = object_property("await_resource")
await_external_ip = object_property("await_external_ip")
await_ingress = object_property("await_ingress")
await_http_ok = object_property("await_http_ok")
await_console_ok = object_property("await_console_ok")

Expand Down
3 changes: 3 additions & 0 deletions external/skewer/python/skewer/standardsteps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ kubernetes/set_up_your_namespaces:
- run: export KUBECONFIG=@kubeconfig@
- run: "# Enter your provider-specific login command"
- run: kubectl create namespace @namespace@
apply: readme
- run: kubectl create namespace @namespace@ --dry-run=client -o yaml | kubectl apply -f -
apply: test
- run: kubectl config set-context --current --namespace @namespace@
kubernetes/set_up_your_kubernetes_namespace:
title: Set up your Kubernetes namespace
Expand Down

0 comments on commit 48efc27

Please sign in to comment.