@@ -3,82 +3,203 @@ package cloudproviderkindinstaller
33import (
44 "context"
55 "fmt"
6- "time"
6+ "io"
7+ "strings"
78
8- "github.com/devantler-tech/ksail/v5/pkg/client/helm"
9+ "github.com/docker/docker/api/types/container"
10+ "github.com/docker/docker/api/types/filters"
11+ "github.com/docker/docker/api/types/image"
12+ "github.com/docker/docker/api/types/mount"
13+ "github.com/docker/docker/api/types/network"
14+ "github.com/docker/docker/client"
915)
1016
11- // CloudProviderKINDInstaller installs or upgrades Cloud Provider KIND.
17+ const (
18+ // CloudProviderKindImage is the official cloud-provider-kind image.
19+ CloudProviderKindImage = "registry.k8s.io/cloud-provider-kind/cloud-controller-manager:latest"
20+ // CloudProviderKindContainerName is the name of the cloud-provider-kind container.
21+ CloudProviderKindContainerName = "cloud-provider-kind"
22+ // CloudProviderKindNetworkName is the default KIND network name.
23+ CloudProviderKindNetworkName = "kind"
24+ // DockerSocketPath is the path to the Docker socket.
25+ DockerSocketPath = "/var/run/docker.sock"
26+ )
27+
28+ // CloudProviderKINDInstaller manages the cloud-provider-kind Docker container.
1229type CloudProviderKINDInstaller struct {
13- kubeconfig string
14- context string
15- timeout time.Duration
16- client helm.Interface
30+ client client.APIClient
1731}
1832
1933// NewCloudProviderKINDInstaller creates a new Cloud Provider KIND installer instance.
2034func NewCloudProviderKINDInstaller (
21- client helm.Interface ,
22- kubeconfig , context string ,
23- timeout time.Duration ,
35+ dockerClient client.APIClient ,
2436) * CloudProviderKINDInstaller {
2537 return & CloudProviderKINDInstaller {
26- client : client ,
27- kubeconfig : kubeconfig ,
28- context : context ,
29- timeout : timeout ,
38+ client : dockerClient ,
3039 }
3140}
3241
33- // Install installs or upgrades Cloud Provider KIND via its Helm chart .
42+ // Install starts the cloud-provider-kind container if not already running .
3443func (c * CloudProviderKINDInstaller ) Install (ctx context.Context ) error {
35- err := c .helmInstallOrUpgradeCloudProviderKIND (ctx )
44+ // Check if container is already running
45+ running , err := c .isContainerRunning (ctx )
3646 if err != nil {
37- return fmt .Errorf ("failed to install cloud-provider-kind: %w" , err )
47+ return fmt .Errorf ("failed to check if container is running: %w" , err )
48+ }
49+
50+ if running {
51+ return nil // Already running
52+ }
53+
54+ // Ensure the cloud-provider-kind image is available
55+ err = c .ensureImage (ctx )
56+ if err != nil {
57+ return fmt .Errorf ("failed to ensure cloud-provider-kind image: %w" , err )
58+ }
59+
60+ // Create and start the container
61+ err = c .createAndStartContainer (ctx )
62+ if err != nil {
63+ return fmt .Errorf ("failed to create and start cloud-provider-kind container: %w" , err )
3864 }
3965
4066 return nil
4167}
4268
43- // Uninstall uninstalls Cloud Provider KIND via Helm .
69+ // Uninstall stops and removes the cloud-provider-kind container .
4470func (c * CloudProviderKINDInstaller ) Uninstall (ctx context.Context ) error {
45- err := c .client . UninstallRelease (ctx , "cloud-provider-kind" , "kube-system" )
71+ containers , err := c .listContainers (ctx )
4672 if err != nil {
47- return fmt .Errorf ("failed to uninstall cloud-provider-kind: %w" , err )
73+ return fmt .Errorf ("failed to list containers: %w" , err )
74+ }
75+
76+ if len (containers ) == 0 {
77+ return nil // Nothing to uninstall
78+ }
79+
80+ // Stop and remove container
81+ for _ , ctr := range containers {
82+ // Stop container if running
83+ if strings .EqualFold (ctr .State , "running" ) {
84+ err = c .client .ContainerStop (ctx , ctr .ID , container.StopOptions {})
85+ if err != nil {
86+ return fmt .Errorf ("failed to stop container: %w" , err )
87+ }
88+ }
89+
90+ // Remove container
91+ err = c .client .ContainerRemove (ctx , ctr .ID , container.RemoveOptions {
92+ Force : true ,
93+ })
94+ if err != nil {
95+ return fmt .Errorf ("failed to remove container: %w" , err )
96+ }
4897 }
4998
5099 return nil
51100}
52101
53102// --- internals ---
54103
55- func (c * CloudProviderKINDInstaller ) helmInstallOrUpgradeCloudProviderKIND (
56- ctx context.Context ,
57- ) error {
58- repoEntry := & helm.RepositoryEntry {
59- Name : "cloud-provider-kind" ,
60- URL : "https://kubernetes-sigs.github.io/cloud-provider-kind" ,
104+ // isContainerRunning checks if the cloud-provider-kind container is running.
105+ func (c * CloudProviderKINDInstaller ) isContainerRunning (ctx context.Context ) (bool , error ) {
106+ containers , err := c .listContainers (ctx )
107+ if err != nil {
108+ return false , err
109+ }
110+
111+ if len (containers ) == 0 {
112+ return false , nil
113+ }
114+
115+ return strings .EqualFold (containers [0 ].State , "running" ), nil
116+ }
117+
118+ // listContainers lists all cloud-provider-kind containers.
119+ func (c * CloudProviderKINDInstaller ) listContainers (ctx context.Context ) ([]container.Summary , error ) {
120+ filterArgs := filters .NewArgs ()
121+ filterArgs .Add ("name" , "^/" + CloudProviderKindContainerName + "$" )
122+
123+ containers , err := c .client .ContainerList (ctx , container.ListOptions {
124+ All : true ,
125+ Filters : filterArgs ,
126+ })
127+ if err != nil {
128+ return nil , fmt .Errorf ("failed to list containers: %w" , err )
61129 }
62130
63- addRepoErr := c .client .AddRepository (ctx , repoEntry , c .timeout )
64- if addRepoErr != nil {
65- return fmt .Errorf ("failed to add cloud-provider-kind repository: %w" , addRepoErr )
131+ return containers , nil
132+ }
133+
134+ // ensureImage pulls the cloud-provider-kind image if not already present.
135+ func (c * CloudProviderKINDInstaller ) ensureImage (ctx context.Context ) error {
136+ // Check if image exists
137+ _ , err := c .client .ImageInspect (ctx , CloudProviderKindImage )
138+ if err == nil {
139+ return nil // Image already exists
140+ }
141+
142+ // Pull image
143+ reader , err := c .client .ImagePull (ctx , CloudProviderKindImage , image.PullOptions {})
144+ if err != nil {
145+ return fmt .Errorf ("failed to pull image: %w" , err )
146+ }
147+ defer reader .Close ()
148+
149+ // Consume pull output
150+ _ , err = io .Copy (io .Discard , reader )
151+ if err != nil {
152+ return fmt .Errorf ("failed to read image pull output: %w" , err )
66153 }
67154
68- spec := & helm.ChartSpec {
69- ReleaseName : "cloud-provider-kind" ,
70- ChartName : "cloud-provider-kind/cloud-provider-kind" ,
71- Namespace : "kube-system" ,
72- RepoURL : "https://kubernetes-sigs.github.io/cloud-provider-kind" ,
73- Atomic : true ,
74- Wait : true ,
75- WaitForJobs : true ,
76- Timeout : c .timeout ,
155+ return nil
156+ }
157+
158+ // createAndStartContainer creates and starts the cloud-provider-kind container.
159+ func (c * CloudProviderKINDInstaller ) createAndStartContainer (ctx context.Context ) error {
160+ // Container configuration
161+ containerConfig := & container.Config {
162+ Image : CloudProviderKindImage ,
163+ }
164+
165+ // Host configuration - mount Docker socket
166+ hostConfig := & container.HostConfig {
167+ Mounts : []mount.Mount {
168+ {
169+ Type : mount .TypeBind ,
170+ Source : DockerSocketPath ,
171+ Target : DockerSocketPath ,
172+ },
173+ },
174+ RestartPolicy : container.RestartPolicy {
175+ Name : "unless-stopped" ,
176+ },
177+ }
178+
179+ // Network configuration - connect to KIND network
180+ networkConfig := & network.NetworkingConfig {
181+ EndpointsConfig : map [string ]* network.EndpointSettings {
182+ CloudProviderKindNetworkName : {},
183+ },
184+ }
185+
186+ // Create container
187+ resp , err := c .client .ContainerCreate (
188+ ctx ,
189+ containerConfig ,
190+ hostConfig ,
191+ networkConfig ,
192+ nil ,
193+ CloudProviderKindContainerName ,
194+ )
195+ if err != nil {
196+ return fmt .Errorf ("failed to create container: %w" , err )
77197 }
78198
79- _ , err := c .client .InstallOrUpgradeChart (ctx , spec )
199+ // Start container
200+ err = c .client .ContainerStart (ctx , resp .ID , container.StartOptions {})
80201 if err != nil {
81- return fmt .Errorf ("failed to install cloud-provider-kind chart : %w" , err )
202+ return fmt .Errorf ("failed to start container : %w" , err )
82203 }
83204
84205 return nil
0 commit comments