feat: implement version checks for extended toolchain

This commit is contained in:
Stefan Reimer 2022-06-28 15:30:13 +02:00
parent a859415a9d
commit 78a902c696
6 changed files with 96 additions and 25 deletions

View File

@ -90,6 +90,7 @@ ENV BUILDAH_ISOLATION=chroot
ENV VIRTUAL_ENV=/venv ENV VIRTUAL_ENV=/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH" ENV PATH="$VIRTUAL_ENV/bin:$PATH"
ENV PULUMI_SKIP_UPDATE_CHECK=true
USER $USER USER $USER

View File

@ -8,8 +8,9 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
from . import __version__ from . import __version__
from .core import CloudBender from .core import CloudBender
from .utils import setup_logging from .utils import setup_logging, get_docker_version
from .exceptions import InvalidProjectDir from .exceptions import InvalidProjectDir
from .pulumi import get_pulumi_version
import logging import logging
@ -17,7 +18,6 @@ logger = logging.getLogger(__name__)
@click.group() @click.group()
@click.version_option(version=__version__, prog_name="CloudBender")
@click.option("--debug", is_flag=True, help="Turn on debug logging.") @click.option("--debug", is_flag=True, help="Turn on debug logging.")
@click.option("--dir", "directory", help="Specify cloudbender project directory.") @click.option("--dir", "directory", help="Specify cloudbender project directory.")
@click.pass_context @click.pass_context
@ -46,6 +46,30 @@ def cli(ctx, debug, directory):
ctx.obj = cb ctx.obj = cb
@click.command()
@click.pass_obj
def version(cb):
"""Displays own version and all dependencies"""
logger.error(f"CloudBender: {__version__}")
# Pulumi
# import pdb;pdb.set_trace()
pulumi_version = get_pulumi_version()
if not pulumi_version:
logger.error(
"Pulumi: Error calling pulumi, see https://www.pulumi.com/docs/get-started/install/"
)
else:
logger.error(f"Pulumi: {pulumi_version}")
# Docker / podman
docker_version = get_docker_version()
if not docker_version:
logger.error("Podman/Docker: Cannot call podman nor docker")
else:
logger.error(f"Podman/Docker: {docker_version}")
@click.command() @click.command()
@click.argument("stack_names", nargs=-1) @click.argument("stack_names", nargs=-1)
@click.option("--multi", is_flag=True, help="Allow more than one stack to match") @click.option("--multi", is_flag=True, help="Allow more than one stack to match")
@ -153,7 +177,7 @@ def refresh(cb, stack_name):
@click.command() @click.command()
@click.argument("stack_name") @click.argument("stack_name")
@click.argument("function", default="") @click.argument("function", default="")
@click.argument('args', nargs=-1) @click.argument("args", nargs=-1)
@click.option( @click.option(
"--listall", "--listall",
is_flag=True, is_flag=True,
@ -168,7 +192,9 @@ def execute(cb, stack_name, function, args, listall=False):
if s.mode == "pulumi": if s.mode == "pulumi":
s.execute(function, args, listall) s.execute(function, args, listall)
else: else:
logger.info("{} uses Cloudformation, no exec feature available.".format(s.stackname)) logger.info(
"{} uses Cloudformation, no exec feature available.".format(s.stackname)
)
@click.command() @click.command()
@ -415,6 +441,7 @@ def _provision(cb, stacks):
future.result() future.result()
cli.add_command(version)
cli.add_command(render) cli.add_command(render)
cli.add_command(sync) cli.add_command(sync)
cli.add_command(validate) cli.add_command(validate)

View File

@ -150,7 +150,7 @@ def gz_pack(source):
out = "" out = ""
# Preserve shebangs (don't care about encodings for this) # Preserve shebangs (don't care about encodings for this)
first_line = source.split("\n")[0] first_line = source.split("\n")[0]
if re.compile('^#!.*$').match(first_line): if re.compile("^#!.*$").match(first_line):
if first_line.rstrip().endswith("python"): if first_line.rstrip().endswith("python"):
first_line = first_line.rstrip() first_line = first_line.rstrip()
first_line += "3" first_line += "3"

View File

@ -5,17 +5,30 @@ import shutil
import tempfile import tempfile
import importlib import importlib
import pulumi import pulumi
import subprocess
from functools import wraps from functools import wraps
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Fail early if pulumi binaries are not available # Disable Pulumis version check globally
if not shutil.which("pulumi"): os.environ["PULUMI_SKIP_UPDATE_CHECK"] = "true"
raise FileNotFoundError(
"Cannot find pulumi binary, see https://www.pulumi.com/docs/get-started/install/"
def get_pulumi_version():
p = shutil.which("pulumi")
if not p:
return None
proc = subprocess.Popen(
[p, "version"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL
) )
if not proc.returncode:
return proc.communicate()[0].decode().strip()
else:
return None
def pulumi_ws(func): def pulumi_ws(func):
@ -36,7 +49,9 @@ def pulumi_ws(func):
_found = False _found = False
try: try:
_stack = importlib.import_module( _stack = importlib.import_module(
"config.{}.{}".format(self.rel_path, self.template).replace("/", ".") "config.{}.{}".format(self.rel_path, self.template).replace(
"/", "."
)
) )
_found = True _found = True
@ -45,7 +60,9 @@ def pulumi_ws(func):
try: try:
spec = importlib.util.spec_from_file_location( spec = importlib.util.spec_from_file_location(
"_stack", "_stack",
"{}/pulumi/{}.py".format(artifacts_path.resolve(), self.template), "{}/pulumi/{}.py".format(
artifacts_path.resolve(), self.template
),
) )
_stack = importlib.util.module_from_spec(spec) _stack = importlib.util.module_from_spec(spec)
spec.loader.exec_module(_stack) spec.loader.exec_module(_stack)
@ -66,7 +83,9 @@ def pulumi_ws(func):
project_name = self.parameters["Conglomerate"] project_name = self.parameters["Conglomerate"]
# Remove stacknameprefix if equals Conglomerate as Pulumi implicitly prefixes project_name # Remove stacknameprefix if equals Conglomerate as Pulumi implicitly prefixes project_name
self.pulumi_stackname = re.sub(r"^" + project_name + "-?", "", self.stackname) self.pulumi_stackname = re.sub(
r"^" + project_name + "-?", "", self.stackname
)
try: try:
pulumi_backend = "{}/{}/{}".format( pulumi_backend = "{}/{}/{}".format(
self.pulumi["backend"], project_name, self.region self.pulumi["backend"], project_name, self.region
@ -111,7 +130,9 @@ def pulumi_ws(func):
secrets_provider == "passphrase" secrets_provider == "passphrase"
and "PULUMI_CONFIG_PASSPHRASE" not in os.environ and "PULUMI_CONFIG_PASSPHRASE" not in os.environ
): ):
raise ValueError("Missing PULUMI_CONFIG_PASSPHRASE environment variable!") raise ValueError(
"Missing PULUMI_CONFIG_PASSPHRASE environment variable!"
)
else: else:
try: try:
@ -136,20 +157,22 @@ def pulumi_ws(func):
) )
_tags["zdt:cloudbender.owner"] = f"{project_name}.{self.pulumi_stackname}" _tags["zdt:cloudbender.owner"] = f"{project_name}.{self.pulumi_stackname}"
self.pulumi_config.update({ self.pulumi_config.update(
"aws:region": self.region, {
"aws:defaultTags": {"tags": _tags}, "aws:region": self.region,
"zdt:region": self.region, "aws:defaultTags": {"tags": _tags},
"zdt:awsAccountId": account_id, "zdt:region": self.region,
"zdt:projectName": project_name, "zdt:awsAccountId": account_id,
"zdt:stackName": self.pulumi_stackname "zdt:projectName": project_name,
}) "zdt:stackName": self.pulumi_stackname,
}
)
# inject all parameters as config in the <Conglomerate> namespace # inject all parameters as config in the <Conglomerate> namespace
for p in self.parameters: for p in self.parameters:
self.pulumi_config["{}:{}".format(self.parameters["Conglomerate"], p)] = self.parameters[ self.pulumi_config[
p "{}:{}".format(self.parameters["Conglomerate"], p)
] ] = self.parameters[p]
stack_settings = pulumi.automation.StackSettings( stack_settings = pulumi.automation.StackSettings(
config=self.pulumi_config, config=self.pulumi_config,

View File

@ -877,7 +877,9 @@ class Stack(object):
if exec_function in vars(self._pulumi_code): if exec_function in vars(self._pulumi_code):
pulumi_stack = self._get_pulumi_stack() pulumi_stack = self._get_pulumi_stack()
vars(self._pulumi_code)[exec_function]( vars(self._pulumi_code)[exec_function](
config=pulumi_stack.get_all_config(), outputs=pulumi_stack.outputs(), args=args config=pulumi_stack.get_all_config(),
outputs=pulumi_stack.outputs(),
args=args,
) )
else: else:

View File

@ -2,6 +2,24 @@ import os
import copy import copy
import logging import logging
import re import re
import shutil
import subprocess
def get_docker_version():
p = shutil.which("podman")
if not p:
p = shutil.which("docker")
if not p:
return None
proc = subprocess.Popen(
[p, "--version"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL
)
if not proc.returncode:
return proc.communicate()[0].decode().strip()
else:
return None
def dict_merge(a, b): def dict_merge(a, b):