Skip to content

Commit e5c2530

Browse files
authored
Fix Skaffold scripts on Windows (#54023)
### Motivation The code made assumptions about the arch and shell of the host machine. ### Additional Notes The final compatibility fix to remove a hardcoded arm64 image is happening separately in #51762 Co-authored-by: ofek.lev <ofek.lev@datadoghq.com>
1 parent 5b4f8c1 commit e5c2530

2 files changed

Lines changed: 87 additions & 18 deletions

File tree

skaffold.yaml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ kind: Config
33
metadata:
44
name: datadog-agent
55
build:
6-
platforms: [ "linux/arm64" ]
76
tagPolicy:
87
gitCommit: {
98
variant: "AbbrevCommitSha"
@@ -18,8 +17,8 @@ deploy:
1817
remoteChart: datadog/datadog
1918
setValueTemplates:
2019
datadog:
21-
apiKey: "{{cmd \"bash\" \"-c\" \"echo $DD_API_KEY\"}}"
22-
appKey: "{{cmd \"bash\" \"-c\" \"echo $DD_APP_KEY\"}}"
20+
apiKey: "{{.DD_API_KEY}}"
21+
appKey: "{{.DD_APP_KEY}}"
2322
kubelet:
2423
tlsVerify: false
2524
agents.image:
@@ -56,9 +55,7 @@ profiles:
5655
artifacts:
5756
- image: agent
5857
custom:
59-
buildCommand: "docker exec datadog-agent-devcontainer bash -c \"
60-
dda inv agent.hacky-dev-image-build --target-image=$IMAGE\""
58+
buildCommand: "dda inv -- skaffold.build --target=agent"
6159
- image: clusteragent
6260
custom:
63-
buildCommand: "docker exec datadog-agent-devcontainer bash -c \"
64-
dda inv cluster-agent.hacky-dev-image-build --target-image=$IMAGE\""
61+
buildCommand: "dda inv -- skaffold.build --target=clusteragent"

tasks/skaffold.py

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Skaffold related tasks
33
"""
44

5+
import os
6+
57
from invoke import UnexpectedExit, task
68
from invoke.exceptions import Exit
79

@@ -11,6 +13,12 @@
1113

1214
DATADOG_AGENT_MOUNT = "/home/datadog/go/src/github.com/DataDog/datadog-agent"
1315

16+
# Maps a Skaffold artifact name to the invoke task that builds its development image.
17+
SKAFFOLD_BUILD_TASKS = {
18+
"agent": "agent.hacky-dev-image-build",
19+
"clusteragent": "cluster-agent.hacky-dev-image-build",
20+
}
21+
1422

1523
@task
1624
def minikube_start(ctx, path: str = ".") -> None:
@@ -50,16 +58,23 @@ def is_minikube_running(ctx) -> bool:
5058
return minikube_status.ok
5159

5260

53-
def generate_minikube_env(ctx) -> list:
61+
def minikube_docker_env(ctx) -> dict:
5462
"""
55-
Generate the Minikube environment variables
63+
Return env vars pointing the Docker CLI at Minikube's daemon, for `ctx.run(env=...)`.
5664
"""
57-
minikube_env = []
58-
minikube_env_command = ctx.run("minikube docker-env", hide=True)
59-
for line in minikube_env_command.stdout.split("\n"):
60-
if line.startswith("export"):
61-
minikube_env.append(line.replace("export ", ""))
62-
return minikube_env
65+
# Shell-agnostic `KEY=value` pairs for easier parsing
66+
result = ctx.run("minikube docker-env --shell none", hide=True)
67+
env = {}
68+
for line in result.stdout.splitlines():
69+
line = line.strip()
70+
if not line or line.startswith("#"):
71+
continue
72+
key, sep, value = line.partition("=")
73+
value = value.strip().strip('"')
74+
# Skip empty assignments (e.g. `SSH_AUTH_SOCK=`) so they don't clobber inherited values.
75+
if sep and value:
76+
env[key.strip()] = value
77+
return env
6378

6479

6580
@task
@@ -104,7 +119,7 @@ def devcontainer_start(ctx) -> None:
104119
"sleep infinity",
105120
]
106121

107-
ctx.run(" ".join(generate_minikube_env(ctx) + docker_command))
122+
ctx.run(" ".join(docker_command), env=minikube_docker_env(ctx))
108123

109124

110125
def is_devcontainer_running(ctx) -> bool:
@@ -119,21 +134,50 @@ def is_devcontainer_running(ctx) -> bool:
119134
"--format",
120135
"{{.Names}}",
121136
]
122-
devcontainer_status = ctx.run(" ".join(generate_minikube_env(ctx) + command), hide=True)
137+
devcontainer_status = ctx.run(" ".join(command), hide=True, env=minikube_docker_env(ctx))
123138
return devcontainer_status.ok and DEVCONTAINER_NAME in devcontainer_status.stdout
124139

125140

141+
def ensure_not_worktree(path: str) -> None:
142+
"""
143+
Exit if `path` is a git worktree.
144+
"""
145+
if os.path.isfile(os.path.join(path, ".git")):
146+
print(
147+
color_message(
148+
f"{os.path.abspath(path)} is a git worktree, which the Skaffold development flow does not "
149+
"support: only this directory is mounted into the build container, but a worktree's git "
150+
"metadata lives in the main repository outside the mount. Run this from a normal clone instead.",
151+
Color.RED,
152+
)
153+
)
154+
raise Exit(code=1)
155+
156+
126157
@task
127158
def create(ctx, path=".") -> None:
128159
"""
129160
Start the Minikube Cluster and the devcontainer
130161
"""
162+
ensure_not_worktree(path)
131163
if not is_minikube_running(ctx):
132164
minikube_start(ctx, path)
133165
if not is_devcontainer_running(ctx):
134166
devcontainer_start(ctx)
135167

136168

169+
@task
170+
def destroy(ctx) -> None:
171+
"""
172+
Remove the devcontainer and delete the Minikube cluster, including anything deployed to it.
173+
"""
174+
if is_minikube_running(ctx):
175+
print(color_message("Removing the devcontainer.", Color.BLUE))
176+
ctx.run(f"docker rm -f {DEVCONTAINER_NAME}", warn=True, env=minikube_docker_env(ctx))
177+
print(color_message("Deleting the Minikube cluster.", Color.BLUE))
178+
ctx.run("minikube delete")
179+
180+
137181
@task
138182
def dev(ctx) -> None:
139183
"""
@@ -158,6 +202,14 @@ def dev(ctx) -> None:
158202
# Create Minikube Cluster and devcontainer if they are not running.
159203
create(ctx)
160204

205+
# The deploy installs the `datadog/datadog` remote chart, so ensure its Helm repo is
206+
# registered and its index cache (kept under a temp dir that may not persist) is fresh.
207+
if not is_installed("helm"):
208+
print(color_message("Helm is not installed. Check https://helm.sh/docs/intro/install.", Color.RED))
209+
raise Exit(code=1)
210+
ctx.run("helm repo add datadog https://helm.datadoghq.com --force-update", warn=True)
211+
ctx.run("helm repo update datadog")
212+
161213
# Create Skaffold Dev command
162214
skaffold_command = [
163215
"skaffold",
@@ -170,4 +222,24 @@ def dev(ctx) -> None:
170222
"--status-check=true",
171223
"--verbosity warn",
172224
]
173-
ctx.run(" ".join(generate_minikube_env(ctx) + skaffold_command))
225+
ctx.run(" ".join(skaffold_command), env=minikube_docker_env(ctx))
226+
227+
228+
@task
229+
def build(ctx, target="agent") -> None:
230+
"""
231+
Build a development image in the running devcontainer, for Skaffold's custom builder.
232+
233+
Assumes that Skaffold has already set the `IMAGE` env var to the target tag.
234+
"""
235+
build_task = SKAFFOLD_BUILD_TASKS.get(target)
236+
if build_task is None:
237+
raise Exit(f"Unknown target '{target}'. Valid targets: {', '.join(SKAFFOLD_BUILD_TASKS)}.", code=1)
238+
239+
target_image = os.environ.get("IMAGE")
240+
if not target_image:
241+
raise Exit("The IMAGE environment variable is not set (it is provided by Skaffold).", code=1)
242+
243+
# Run via a login shell to ensure proper environment setup.
244+
inner = f"dda inv -- {build_task} --target-image={target_image}"
245+
ctx.run(f'docker exec {DEVCONTAINER_NAME} bash -lc "{inner}"', env=minikube_docker_env(ctx))

0 commit comments

Comments
 (0)