Skip to content

Commit 7584d40

Browse files
authored
Merge pull request #50 from ArchetypicalSoftware/hotfix/dockerhub-local
This pull request introduces improvements to the Kubernetes cluster creation process and enhances the robustness of the Flux deployment workflow. The main changes include updating the default Kubernetes version, ensuring proper configuration file handling for containerd, and adding a mechanism to wait for all Flux kustomizations to be ready before proceeding.
2 parents f253095 + 313afbc commit 7584d40

File tree

4 files changed

+116
-5
lines changed

4 files changed

+116
-5
lines changed

.claude/settings.local.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,17 @@
22
"permissions": {
33
"allow": [
44
"Bash(docker stop:*)",
5-
"Bash(docker rm:*)"
5+
"Bash(docker rm:*)",
6+
"Bash(docker run:*)",
7+
"Bash(MSYS_NO_PATHCONV=1 docker run:*)",
8+
"Bash(MSYS_NO_PATHCONV=1 docker exec:*)",
9+
"Bash(for node in idp-worker idp-worker2)",
10+
"Bash(do:*)",
11+
"Bash(echo:*)",
12+
"Bash(done)",
13+
"Bash(for node in idp-control-plane idp-worker idp-worker2)",
14+
"Bash(kubectl --context kind-idp get pods:*)",
15+
"Bash(kubectl --context kind-idp delete pod:*)"
616
]
717
}
818
}

cli/src/Vdk/Commands/CreateClusterCommand.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public CreateClusterCommand(
5151
controlNodes.Aliases.Add("-c");
5252
var workers = new Option<int>("--Workers") { DefaultValueFactory = _ => Defaults.WorkerNodes, Description = "The number of worker nodes in the cluster." };
5353
workers.Aliases.Add("-w");
54-
var kubeVersion = new Option<string>("--KubeVersion") { DefaultValueFactory = _ => "1.29", Description = "The kubernetes api version." };
54+
var kubeVersion = new Option<string>("--KubeVersion") { DefaultValueFactory = _ => "1.32", Description = "The kubernetes api version." };
5555
kubeVersion.Aliases.Add("-k");
5656

5757
Options.Add(nameOption);
@@ -111,6 +111,16 @@ public async Task InvokeAsync(string name = Defaults.ClusterName, int controlPla
111111
return;
112112
}
113113

114+
// Write hosts.toml to a temp file for containerd registry config
115+
// This ensures the file is accessible to Docker regardless of working directory
116+
var hostsTomlContent = """
117+
server = "http://host.docker.internal:5000"
118+
[host."http://host.docker.internal:5000"]
119+
capabilities = ["pull", "resolve"]
120+
""";
121+
var hostsTomlPath = _fileSystem.Path.Combine(_fileSystem.Path.GetTempPath(), $"hosts-{Guid.NewGuid()}.toml");
122+
await _fileSystem.File.WriteAllTextAsync(hostsTomlPath, hostsTomlContent);
123+
114124
var cluster = new KindCluster();
115125
for (int index = 0; index < controlPlaneNodes; index++)
116126
{
@@ -127,7 +137,7 @@ public async Task InvokeAsync(string name = Defaults.ClusterName, int controlPla
127137
{
128138
new()
129139
{
130-
HostPath = _fileSystem.FileInfo.New("ConfigMounts/hosts.toml").FullName,
140+
HostPath = hostsTomlPath,
131141
ContainerPath = "/etc/containerd/certs.d/hub.dev-k8s.cloud/hosts.toml"
132142
}
133143
};
@@ -144,7 +154,7 @@ public async Task InvokeAsync(string name = Defaults.ClusterName, int controlPla
144154
{
145155
new()
146156
{
147-
HostPath = _fileSystem.FileInfo.New("ConfigMounts/hosts.toml").FullName,
157+
HostPath = hostsTomlPath,
148158
ContainerPath = "/etc/containerd/certs.d/hub.dev-k8s.cloud/hosts.toml"
149159
}
150160
}
@@ -194,6 +204,10 @@ public async Task InvokeAsync(string name = Defaults.ClusterName, int controlPla
194204
}
195205

196206
_flux.Bootstrap(name.ToLower(), "./clusters/default", branch: "main");
207+
208+
// Wait for all Flux kustomizations to reconcile before configuring the reverse proxy
209+
_flux.WaitForKustomizations(name.ToLower());
210+
197211
try
198212
{
199213
_reverseProxy.UpsertCluster(name.ToLower(), masterNode.ExtraPortMappings.First().HostPort,

cli/src/Vdk/Services/FluxClient.cs

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Net;
2+
using System.Text.Json;
23
using k8s;
34
using k8s.Autorest;
45
using k8s.Models;
@@ -114,6 +115,91 @@ public void Bootstrap(string clusterName, string path, string branch = DefaultBr
114115
}
115116

116117
_console.WriteLine("Flux bootstrap complete.");
117-
118+
119+
}
120+
121+
public bool WaitForKustomizations(string clusterName, int maxAttempts = 60, int delaySeconds = 5)
122+
{
123+
_console.WriteLine("Waiting for Flux kustomizations to reconcile...");
124+
125+
for (int attempt = 0; attempt < maxAttempts; attempt++)
126+
{
127+
try
128+
{
129+
var result = _client(clusterName).ApiClient.CustomObjects
130+
.ListNamespacedCustomObject(
131+
"kustomize.toolkit.fluxcd.io", "v1",
132+
"flux-system", "kustomizations");
133+
134+
var json = JsonSerializer.Serialize(result);
135+
using var doc = JsonDocument.Parse(json);
136+
var items = doc.RootElement.GetProperty("items");
137+
138+
if (items.GetArrayLength() == 0)
139+
{
140+
if (attempt % 5 == 0)
141+
_console.WriteLine(" No kustomizations found yet. Waiting...");
142+
Thread.Sleep(delaySeconds * 1000);
143+
continue;
144+
}
145+
146+
int total = items.GetArrayLength();
147+
int readyCount = 0;
148+
149+
foreach (var item in items.EnumerateArray())
150+
{
151+
var name = item.GetProperty("metadata").GetProperty("name").GetString();
152+
bool isReady = false;
153+
154+
if (item.TryGetProperty("status", out var status) &&
155+
status.TryGetProperty("conditions", out var conditions))
156+
{
157+
foreach (var condition in conditions.EnumerateArray())
158+
{
159+
if (condition.GetProperty("type").GetString() == "Ready")
160+
{
161+
var condStatus = condition.GetProperty("status").GetString();
162+
if (condStatus == "True")
163+
{
164+
isReady = true;
165+
}
166+
else if (attempt % 5 == 0)
167+
{
168+
var reason = condition.TryGetProperty("reason", out var r)
169+
? r.GetString() : "Unknown";
170+
var message = condition.TryGetProperty("message", out var m)
171+
? m.GetString() : "";
172+
_console.WriteLine(
173+
$" Kustomization '{name}' not ready: {reason} - {message}");
174+
}
175+
break;
176+
}
177+
}
178+
}
179+
180+
if (isReady) readyCount++;
181+
}
182+
183+
if (attempt % 5 == 0 || readyCount == total)
184+
_console.WriteLine($" Kustomizations ready: {readyCount}/{total}");
185+
186+
if (readyCount == total)
187+
{
188+
_console.WriteLine("All Flux kustomizations are ready.");
189+
return true;
190+
}
191+
}
192+
catch (Exception ex)
193+
{
194+
if (attempt % 5 == 0)
195+
_console.WriteLine($" Error checking kustomizations: {ex.Message}. Retrying...");
196+
}
197+
198+
Thread.Sleep(delaySeconds * 1000);
199+
}
200+
201+
_console.WriteWarning(
202+
"Timed out waiting for Flux kustomizations to reconcile. Proceeding anyway...");
203+
return false;
118204
}
119205
}

cli/src/Vdk/Services/IFluxClient.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ namespace Vdk.Services;
33
public interface IFluxClient
44
{
55
void Bootstrap(string clusterName, string path, string branch = FluxClient.DefaultBranch);
6+
bool WaitForKustomizations(string clusterName, int maxAttempts = 60, int delaySeconds = 5);
67
}

0 commit comments

Comments
 (0)