99 "strings"
1010 "time"
1111
12+ "github.com/aifoundry-org/oxide-controller/pkg/config"
1213 "github.com/aifoundry-org/oxide-controller/pkg/util"
1314 "k8s.io/client-go/kubernetes"
1415 "tailscale.com/client/tailscale/v2"
@@ -18,51 +19,36 @@ import (
1819)
1920
2021type Cluster struct {
21- logger * log. Entry
22- oxideConfig * oxide. Config
23- projectID string
24- controlPlanePrefix string
25- workerPrefix string
26- controlPlaneCount int
27- clusterInitWait time. Duration
22+ // logger
23+ logger * log. Entry
24+
25+ // reusable config that should be loaded into the secret and shared, whether running locally or in-cluster
26+ config * config. ControllerConfig
27+
28+ // config that is derived locally
2829 kubeconfigOverwrite bool
29- // workerCount per the CLI flags; once cluster is up and running, relies solely on amount stored in secret
30- workerCount int
31- controlPlaneSpec , workerSpec NodeSpec
32- secretName string
33- namespace string
34- userPubkey []byte
35- controlPlaneIP string
36- imageParallelism int
37- tailscaleAPIKey string
38- tailscaleTailnet string
39- clientset * kubernetes.Clientset
40- apiConfig * Config
41- ociImage string
30+ ociImage string // OCI image to use for the controller
31+ oxideConfig * oxide.Config
32+ clientset * kubernetes.Clientset
33+ apiConfig * Config
34+ projectID string // ID of the Oxide project
35+ initWait time.Duration // time to wait for the cluster to initialize
4236}
4337
4438// New creates a new Cluster instance
45- func New (logger * log.Entry , oxideConfig * oxide.Config , projectID string , controlPlanePrefix , workerPrefix string , controlPlaneCount , workerCount int , controlPlaneSpec , workerSpec NodeSpec , imageParallelism int , namespace , secretName string , pubkey []byte , clusterInitWait time.Duration , kubeconfigOverwrite bool , tailscaleAPIKey , tailscaleTailnet , OCIimage string ) * Cluster {
39+ func New (logger * log.Entry , ctrlrConfig * config.ControllerConfig , kubeconfigOverwrite bool , ociImage string , initWait time.Duration ) * Cluster {
40+ //oxideConfig *oxide.Config, projectID string, controlPlanePrefix, workerPrefix string, controlPlaneCount, workerCount int, controlPlaneSpec, workerSpec NodeSpec, imageParallelism int, namespace, secretName string, pubkey []byte, clusterInitWait time.Duration, kubeconfigOverwrite bool, tailscaleAPIKey, tailscaleTailnet, OCIimage string)
4641 c := & Cluster {
47- logger : logger .WithField ("component" , "cluster" ),
48- oxideConfig : oxideConfig ,
49- projectID : projectID ,
50- controlPlanePrefix : controlPlanePrefix ,
51- workerPrefix : workerPrefix ,
52- controlPlaneSpec : controlPlaneSpec ,
53- workerSpec : workerSpec ,
54- secretName : secretName ,
55- namespace : namespace ,
56- userPubkey : pubkey ,
57- clusterInitWait : clusterInitWait ,
42+ logger : logger .WithField ("component" , "cluster" ),
43+ config : ctrlrConfig ,
44+ oxideConfig : & oxide.Config {
45+ Token : ctrlrConfig .OxideToken ,
46+ Host : ctrlrConfig .OxideURL ,
47+ },
5848 kubeconfigOverwrite : kubeconfigOverwrite ,
59- imageParallelism : imageParallelism ,
60- tailscaleAPIKey : tailscaleAPIKey ,
61- tailscaleTailnet : tailscaleTailnet ,
62- ociImage : OCIimage ,
49+ ociImage : ociImage ,
50+ initWait : initWait ,
6351 }
64- c .workerCount = workerCount
65- c .controlPlaneCount = controlPlaneCount
6652 return c
6753}
6854
@@ -74,18 +60,18 @@ func (c *Cluster) ensureClusterExists(ctx context.Context) (newKubeconfig []byte
7460 return nil , fmt .Errorf ("failed to create Oxide API client: %v" , err )
7561 }
7662 projectID := c .projectID
77- controlPlanePrefix := c .controlPlanePrefix
78- controlPlaneCount := c .controlPlaneCount
79- secretName := c .secretName
63+ controlPlanePrefix := c .config . ControlPlaneSpec . Prefix
64+ controlPlaneCount := c .config . ControlPlaneCount
65+ secretName := c .config . SecretName
8066
8167 c .logger .Debugf ("Checking if control plane IP %s exists" , controlPlanePrefix )
8268 controlPlaneIP , err := c .ensureControlPlaneIP (ctx , controlPlanePrefix )
8369 if err != nil {
8470 return nil , fmt .Errorf ("failed to get control plane IP: %w" , err )
8571 }
8672
87- if c .controlPlaneIP == "" {
88- c .controlPlaneIP = controlPlaneIP .Ip
73+ if c .config . ControlPlaneIP == "" {
74+ c .config . ControlPlaneIP = controlPlaneIP .Ip
8975 }
9076
9177 c .logger .Debugf ("Checking if %d control plane nodes exist with prefix %s" , controlPlaneCount , controlPlanePrefix )
@@ -146,8 +132,8 @@ func (c *Cluster) ensureClusterExists(ctx context.Context) (newKubeconfig []byte
146132 return nil , fmt .Errorf ("failed to generate SSH key pair: %w" , err )
147133 }
148134 var pubkeyList []string
149- if c .userPubkey != nil {
150- pubkeyList = append (pubkeyList , string ( c . userPubkey ) )
135+ if c .config . UserSSHPublicKey != "" {
136+ pubkeyList = append (pubkeyList , c . config . UserSSHPublicKey )
151137 }
152138 pubkeyList = append (pubkeyList , string (pub ))
153139 // add the public key to the node in addition to the user one
@@ -166,7 +152,7 @@ func (c *Cluster) ensureClusterExists(ctx context.Context) (newKubeconfig []byte
166152 externalIP string
167153 fipAttached bool
168154 )
169- if c .controlPlaneSpec .ExternalIP {
155+ if c .config . ControlPlaneSpec .ExternalIP {
170156 c .logger .Debugf ("Control plane node %s has external IP, using that" , hostid )
171157 ipList , err := client .InstanceExternalIpList (ctx , oxide.InstanceExternalIpListParams {
172158 Instance : oxide .NameOrId (hostid ),
@@ -215,18 +201,18 @@ func (c *Cluster) ensureClusterExists(ctx context.Context) (newKubeconfig []byte
215201 clusterAccessIP := externalIP
216202
217203 // wait for the control plane node to be up and running
218- timeLeft := c .clusterInitWait
204+ timeLeft := c .initWait
219205 for {
220206 c .logger .Infof ("Waiting %s for control plane node to be up and running..." , timeLeft )
221207 sleepTime := 30 * time .Second
222208 time .Sleep (sleepTime )
223209 timeLeft -= sleepTime
224210
225- if c .tailscaleAPIKey != "" {
211+ if c .config . TailscaleAPIKey != "" {
226212 c .logger .Infof ("Checking if control plane node has joined tailnet" )
227213 client := & tailscale.Client {
228- Tailnet : c .tailscaleTailnet ,
229- APIKey : c .tailscaleAPIKey ,
214+ Tailnet : c .config . TailscaleTailnet ,
215+ APIKey : c .config . TailscaleAPIKey ,
230216 }
231217 ctx := context .Background ()
232218 devices , err := client .Devices ().List (ctx )
@@ -286,16 +272,9 @@ func (c *Cluster) ensureClusterExists(ctx context.Context) (newKubeconfig []byte
286272 return nil , fmt .Errorf ("failed to run command to retrieve join token on control plane node: %w" , err )
287273 }
288274 // save the private key and public key to the secret
289- secrets [secretKeySystemSSHPublic ] = pub
290- secrets [secretKeySystemSSHPrivate ] = priv
291- secrets [secretKeyJoinToken ] = joinToken
292- secrets [secretKeyOxideToken ] = []byte (c .oxideConfig .Token )
293- secrets [secretKeyOxideURL ] = []byte (c .oxideConfig .Host )
294-
295- // save the user ssh public key to the secrets map
296- if c .userPubkey != nil {
297- secrets [secretKeyUserSSH ] = c .userPubkey
298- }
275+ c .config .K3sJoinToken = string (joinToken )
276+ c .config .SystemSSHPublicKey = string (pub )
277+ c .config .SystemSSHPrivateKey = string (priv )
299278
300279 // get the kubeconfig
301280 kubeconfig , err := util .RunSSHCommand ("root" , fmt .Sprintf ("%s:22" , clusterAccessIP ), priv , "cat /etc/rancher/k3s/k3s.yaml" )
@@ -310,10 +289,6 @@ func (c *Cluster) ensureClusterExists(ctx context.Context) (newKubeconfig []byte
310289 re := regexp .MustCompile (`(server:\s*\w+://)(\d+\.\d+\.\d+\.\d+)(:\d+)` )
311290 kubeconfigString = re .ReplaceAllString (kubeconfigString , fmt .Sprintf ("${1}%s${3}" , clusterAccessIP ))
312291
313- // if we have worker node count explicitly defined, save it
314- if c .workerCount > 0 {
315- secrets [secretKeyWorkerCount ] = []byte (fmt .Sprintf ("%d" , c .workerCount ))
316- }
317292 newKubeconfig = []byte (kubeconfigString )
318293
319294 // get a Kubernetes client
@@ -329,12 +304,18 @@ func (c *Cluster) ensureClusterExists(ctx context.Context) (newKubeconfig []byte
329304 c .clientset = clientset
330305
331306 // ensure we have the namespace we need
332- namespace := c .namespace
307+ namespace := c .config . ControlPlaneNamespace
333308 if err := createNamespace (ctx , clientset , namespace ); err != nil {
334309 return nil , fmt .Errorf ("failed to create namespace: %w" , err )
335310 }
336311
337- // save the join token, system ssh key pair, user ssh key to the Kubernetes secret
312+ configJson , err := c .config .ToJSON ()
313+ if err != nil {
314+ return nil , fmt .Errorf ("failed to convert config to JSON: %w" , err )
315+ }
316+ secrets [secretKeyConfig ] = configJson
317+
318+ // save the config to the Kubernetes secret
338319 c .logger .Debugf ("Saving secret %s/%s to Kubernetes" , namespace , secretName )
339320 if err := saveSecret (ctx , clientset , c .logger , namespace , secretName , secrets ); err != nil {
340321 return nil , fmt .Errorf ("failed to save secret: %w" , err )
0 commit comments