Skip to content

Commit 1c04349

Browse files
authored
Merge pull request #1174 from projectsyn/feat/external-tool-mgmt
Add commands to manage required external tools
2 parents b587e08 + af428f4 commit 1c04349

23 files changed

Lines changed: 3990 additions & 79 deletions

.github/workflows/test.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,4 @@ jobs:
163163
run: make docker
164164
- name: Run image
165165
run: |
166-
docker run docker.io/projectsyn/commodore:test || exit_code=$?
167-
if [ "$exit_code" -ne 2 ]; then
168-
echo "Unexpected exit code $exit_code, expected 2"
169-
exit $exit_code
170-
fi
166+
docker run docker.io/projectsyn/commodore:test version

Dockerfile

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ ARG POETRY_VERSION=1.8.5
1515
RUN apt-get update && apt-get install -y --no-install-recommends \
1616
build-essential \
1717
curl \
18+
git \
1819
libffi-dev \
1920
&& rm -rf /var/lib/apt/lists/* \
2021
&& curl -sSL https://install.python-poetry.org | python - --version ${POETRY_VERSION} \
@@ -37,22 +38,13 @@ RUN sed -i "s/^__git_version__.*$/__git_version__ = '${GITVERSION}'/" commodore/
3738

3839
RUN pip install ./dist/syn_commodore-*-py3-none-any.whl
3940

40-
RUN curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 \
41-
&& chmod 700 get_helm.sh \
42-
&& ./get_helm.sh \
43-
&& mv /usr/local/bin/helm /usr/local/bin/helm3 \
44-
&& curl -LO https://git.io/get_helm.sh \
45-
&& chmod 700 get_helm.sh \
46-
&& ./get_helm.sh \
47-
&& mv /usr/local/bin/helm /usr/local/bin/helm2
48-
4941
ARG KUSTOMIZE_VERSION=5.7.0
5042
ARG JSONNET_BUNDLER_VERSION=v0.6.3
43+
ARG HELM_VERSION=v3.18.4
5144

52-
RUN ./tools/install-jb.sh ${JSONNET_BUNDLER_VERSION} \
53-
&& curl -fsSLO "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" \
54-
&& chmod +x install_kustomize.sh \
55-
&& ./install_kustomize.sh ${KUSTOMIZE_VERSION} /usr/local/bin
45+
RUN commodore tool install helm --version ${HELM_VERSION} \
46+
&& commodore tool install kustomize --version ${KUSTOMIZE_VERSION} \
47+
&& commodore tool install jb --version ${JSONNET_BUNDLER_VERSION}
5648

5749
FROM base AS runtime
5850

@@ -73,12 +65,17 @@ COPY --from=builder \
7365
COPY --from=builder \
7466
/usr/local/bin/kapitan* \
7567
/usr/local/bin/commodore* \
76-
/usr/local/bin/helm* \
77-
/usr/local/bin/jb \
78-
/usr/local/bin/kustomize \
7968
/usr/local/bin/
8069

81-
RUN ln -s /usr/local/bin/helm3 /usr/local/bin/helm
70+
COPY --from=builder \
71+
/app/.cache/commodore/tools/ \
72+
/app/.cache/commodore/tools/
73+
74+
RUN ln -s \
75+
/app/.cache/commodore/tools/helm \
76+
/app/.cache/commodore/tools/jb \
77+
/app/.cache/commodore/tools/kustomize \
78+
/usr/local/bin/
8279

8380
COPY ./tools/entrypoint.sh /usr/local/bin/
8481

commodore/cli/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
from reclass_rs import Reclass
1010

1111
from dotenv import load_dotenv, find_dotenv
12-
from commodore import __git_version__, __version__
12+
13+
from commodore import __git_version__, __version__, tools
1314
from commodore.config import Config
1415
from commodore.version import version_info
1516

@@ -20,6 +21,7 @@
2021
from .inventory import inventory_group
2122
from .package import package_group
2223
from .oidc import commodore_fetch_token, commodore_login
24+
from .tool import tool_group
2325

2426

2527
def _version():
@@ -75,6 +77,7 @@ def commodore(ctx, working_dir, verbose, request_timeout):
7577
commodore.add_command(component_group)
7678
commodore.add_command(inventory_group)
7779
commodore.add_command(package_group)
80+
commodore.add_command(tool_group)
7881
commodore.add_command(commodore_login)
7982
commodore.add_command(commodore_fetch_token)
8083
commodore.add_command(commodore_version)
@@ -83,6 +86,7 @@ def commodore(ctx, working_dir, verbose, request_timeout):
8386
def main():
8487
multiprocessing.set_start_method("spawn")
8588
Reclass.set_thread_count(0)
89+
tools.setup_path()
8690

8791
load_dotenv(dotenv_path=find_dotenv(usecwd=True))
8892
commodore.main(

commodore/cli/tool.py

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
from typing import Optional
2+
3+
import click
4+
5+
import commodore.cli.options as options
6+
7+
from commodore import tools
8+
from commodore.config import Config
9+
10+
11+
@click.group(
12+
name="tool",
13+
short_help="Manage required external tools",
14+
)
15+
@options.verbosity
16+
@options.pass_config
17+
@options.github_token
18+
def tool_group(config: Config, verbose: int, github_token: str):
19+
"""Commands to manage required external tools.
20+
21+
Currently, `helm`, jsonnet-bundler/`jb`, and `kustomize` are required
22+
external tools.
23+
"""
24+
config.update_verbosity(verbose)
25+
config.managed_tools = tools.load_state()
26+
config.github_token = github_token
27+
28+
29+
@tool_group.command(name="list", short_help="List external tools")
30+
@options.verbosity
31+
@options.pass_config
32+
@options.github_token
33+
@click.option(
34+
"--version-check/--skip-version-check",
35+
" / -V",
36+
default=True,
37+
help="Query GitHub API to get latest version",
38+
)
39+
def tool_list(config: Config, verbose: int, github_token: str, version_check: bool):
40+
"""List the version, location and management state of the required external tools.
41+
42+
Currently, `helm`, jsonnet-bundler/`jb`, and `kustomize` are required
43+
external tools. By default, the command also queries the GitHub API to
44+
determine the latest available version of each tool and indicates whether an
45+
update is available.
46+
47+
Optionally, the command accepts a GitHub personal access token (PAT) to
48+
avoid running into the fairly strict unauthenticated GitHub rate limits.
49+
"""
50+
config.update_verbosity(verbose)
51+
config.github_token = github_token
52+
tools.list_tools(config, version_check)
53+
54+
55+
@tool_group.command(name="install", short_help="Install external tools")
56+
@options.verbosity
57+
@options.pass_config
58+
@options.github_token
59+
@click.option(
60+
"--version",
61+
default=None,
62+
metavar="VERSION",
63+
help="A version to install for the requested tool. "
64+
+ "By default, the latest version is installed.",
65+
)
66+
@click.option(
67+
"--missing",
68+
is_flag=True,
69+
default=False,
70+
help="Install the latest version for all currently unmanaged tools. "
71+
+ "This flag and providing a tool name on the command line are mutually exclusive.",
72+
)
73+
@click.argument("tool", required=False, default="")
74+
def tool_install(
75+
config: Config,
76+
verbose: int,
77+
tool: str,
78+
version: Optional[str],
79+
github_token: str,
80+
missing: bool,
81+
):
82+
"""Install one of the required tools in `$XDG_CACHE_DIR/commodore/tools`.
83+
84+
The command will fail for tools which are already managed by Commodore.
85+
86+
By default, the command will install the latest available tool version. For
87+
`helm` and `kustomize`, the command downloads the official installation
88+
scripts and executes them with appropriate arguments. For `jb`, the command
89+
directly downloads the requested version from the GitHub release page.
90+
91+
Optionally, the command accepts a tool version to install. The command
92+
accepts versions prefixed with "v" and unprefixed versions.
93+
94+
Alternatively, the command can install the latest version for all required
95+
tools which aren't managed by Commodore yet by passing flag `--missing`.
96+
This flag is mutually exclusive with providing a tool name.
97+
"""
98+
config.update_verbosity(verbose)
99+
config.github_token = github_token
100+
101+
if not tool and not missing or tool and missing:
102+
raise click.ClickException(
103+
"`commodore tool install` expects to be called with either a tool name or the `--missing` flag."
104+
)
105+
if missing and version:
106+
click.secho(
107+
"Flag `--version` has no effect when calling the command with `--missing`.",
108+
fg="yellow",
109+
)
110+
111+
if missing:
112+
tools.install_missing_tools(config)
113+
else:
114+
tools.install_tool(config, tool, version)
115+
116+
117+
@tool_group.command(name="upgrade", short_help="Upgrade external tools")
118+
@options.verbosity
119+
@options.github_token
120+
@options.pass_config
121+
@click.option(
122+
"--version",
123+
default=None,
124+
metavar="VERSION",
125+
help="A version to upgrade (or downgrade) to for the requested tool. "
126+
+ "By default, the tool is upgraded to the latest version.",
127+
)
128+
@click.option(
129+
"--all",
130+
is_flag=True,
131+
default=False,
132+
help="Upgrade all currently managed tools to their latest versions. "
133+
+ "This flag and providing a tool name on the command line are mutually exclusive.",
134+
)
135+
@click.argument("tool", required=False, default="")
136+
def tool_upgrade(
137+
config: Config,
138+
verbose: int,
139+
tool: str,
140+
version: Optional[str],
141+
github_token: str,
142+
all: bool,
143+
):
144+
"""Upgrade (or downgrade) one of the required tools in `$XDG_CACHE_DIR/commodore/tools`.
145+
146+
The command will fail for tools which aren't managed by Commodore yet.
147+
148+
By default, the command will upgrade the tool to the latest available
149+
version. For `helm` and `kustomize`, the command downloads the official
150+
installation scripts and executes them with appropriate arguments. For `jb`,
151+
the command directly downloads the requested version from the GitHub release
152+
page.
153+
154+
Optionally, the command accepts a tool version to upgrade (or downgrade) to.
155+
The command accepts versions prefixed with "v" and unprefixed versions.
156+
157+
Alternatively, the command can upgrade all managed tools to their latest
158+
versions by passing flag `--all`. This flag is mutually exclusive with
159+
providing a tool name.
160+
"""
161+
config.update_verbosity(verbose)
162+
config.github_token = github_token
163+
164+
if not tool and not all or tool and all:
165+
raise click.ClickException(
166+
"`commodore tool upgrade` expects to be called with either a tool name or the `--all` flag."
167+
)
168+
if all and version:
169+
click.secho(
170+
"Flag `--version` has no effect when calling the command with `--all`.",
171+
fg="yellow",
172+
)
173+
if all:
174+
tools.upgrade_all_tools(config)
175+
else:
176+
tools.upgrade_tool(config, tool, version)

commodore/config.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class Config:
101101
_dynamic_facts: dict[str, Any]
102102
_github_token: Optional[str]
103103
_request_timeout: int
104+
_managed_tools: dict[str, str]
104105

105106
oidc_client: Optional[str]
106107
oidc_discovery_url: Optional[str]
@@ -141,6 +142,7 @@ def __init__(
141142
self._dynamic_facts = {}
142143
self._github_token = None
143144
self._request_timeout = 5
145+
self._managed_tools = {}
144146

145147
@property
146148
def verbose(self):
@@ -316,6 +318,14 @@ def request_timeout(self) -> int:
316318
def request_timeout(self, timeout: int):
317319
self._request_timeout = timeout
318320

321+
@property
322+
def managed_tools(self) -> dict[str, str]:
323+
return self._managed_tools
324+
325+
@managed_tools.setter
326+
def managed_tools(self, managed_tools: dict[str, str]):
327+
self._managed_tools = managed_tools
328+
319329
@property
320330
def inventory(self):
321331
return self._inventory

0 commit comments

Comments
 (0)