Skip to content

Commit 4457c94

Browse files
Add support for lookup of nodepool image if not present (#216)
1 parent ad5bc13 commit 4457c94

File tree

13 files changed

+643
-25
lines changed

13 files changed

+643
-25
lines changed

cloud/scope/managed_machine_pool.go

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"reflect"
2424
"sort"
2525
"strconv"
26+
"strings"
2627

2728
"github.com/go-logr/logr"
2829
infrastructurev1beta1 "github.com/oracle/cluster-api-provider-oci/api/v1beta1"
@@ -43,7 +44,9 @@ import (
4344
"sigs.k8s.io/controller-runtime/pkg/client"
4445
)
4546

46-
const OCIManagedMachinePoolKind = "OCIManagedMachinePool"
47+
const (
48+
OCIManagedMachinePoolKind = "OCIManagedMachinePool"
49+
)
4750

4851
// ManagedMachinePoolScopeParams defines the params need to create a new ManagedMachinePoolScope
4952
type ManagedMachinePoolScopeParams struct {
@@ -267,11 +270,14 @@ func (m *ManagedMachinePoolScope) CreateNodePool(ctx context.Context) (*oke.Node
267270
nodeShapeConfig.MemoryInGBs = common.Float32(float32(memoryInGBs))
268271
}
269272
}
273+
err = m.setNodepoolImageId(ctx)
274+
if err != nil {
275+
return nil, err
276+
}
270277
sourceDetails := oke.NodeSourceViaImageDetails{
271-
ImageId: m.OCIManagedMachinePool.Spec.NodeSourceViaImage.ImageId,
278+
ImageId: machinePool.Spec.NodeSourceViaImage.ImageId,
272279
BootVolumeSizeInGBs: machinePool.Spec.NodeSourceViaImage.BootVolumeSizeInGBs,
273280
}
274-
275281
podNetworkOptions := machinePool.Spec.NodePoolNodeConfig.NodePoolPodNetworkOptionDetails
276282
if podNetworkOptions != nil {
277283
if podNetworkOptions.CniType == expinfra1.VCNNativeCNI {
@@ -343,6 +349,80 @@ func (m *ManagedMachinePoolScope) CreateNodePool(ctx context.Context) (*oke.Node
343349
return m.getOKENodePoolFromOCID(ctx, nodePoolId)
344350
}
345351

352+
func (m *ManagedMachinePoolScope) setNodepoolImageId(ctx context.Context) error {
353+
imageId := m.OCIManagedMachinePool.Spec.NodeSourceViaImage.ImageId
354+
if imageId != nil && *imageId != "" {
355+
return nil
356+
}
357+
response, err := m.ContainerEngineClient.GetNodePoolOptions(ctx, oke.GetNodePoolOptionsRequest{
358+
NodePoolOptionId: common.String("all"),
359+
CompartmentId: common.String(m.OCIManagedCluster.Spec.CompartmentId),
360+
})
361+
if err != nil {
362+
m.Logger.Error(err, "Could not lookup node pool options")
363+
return err
364+
}
365+
// version in the capoci spec starts with v, wheres as in the node pool options API in OKE
366+
// the image name does not contain . For example
367+
// {
368+
// "image-id": "ocid1.image.oc1.iad.aaaaaaaafp7ysdbfl2bg67s4jzbpewxo3k772baixa3vwzecwogl474qecza",
369+
// "source-name": "Oracle-Linux-8.6-aarch64-2022.12.15-0-OKE-1.25.4-543",
370+
// "source-type": "IMAGE"
371+
// },
372+
// {
373+
// "image-id": "ocid1.image.oc1.iad.aaaaaaaauwwokidwf5nfi34ucbvgnjsni3klnfmu6pz73ctdohb2byiw6ztq",
374+
// "source-name": "Oracle-Linux-8.6-2022.12.15-0-OKE-1.23.4-543",
375+
// "source-type": "IMAGE"
376+
// },
377+
// we will only default to non gpu image
378+
379+
// proper validation exists in webhook, this is to be fail-safe
380+
specVersion := m.OCIManagedMachinePool.Spec.Version
381+
if specVersion == nil || len(*specVersion) < 1 {
382+
return errors.New(fmt.Sprintf("invalid/nil kubernetes version is set in OCIManagedMachinePool Spec"))
383+
}
384+
k8sVersion := (*specVersion)[1:]
385+
shape := m.OCIManagedMachinePool.Spec.NodeShape
386+
isArmShape := strings.Contains(shape, "A1")
387+
for _, source := range response.Sources {
388+
image, ok := source.(oke.NodeSourceViaImageOption)
389+
if ok {
390+
sourceName := *image.SourceName
391+
if isValidImage(sourceName) {
392+
// if source is an arm source and expectation is not an arm image, ignore
393+
if strings.Contains(sourceName, "aarch64") && !isArmShape {
394+
continue
395+
}
396+
if strings.Contains(sourceName, k8sVersion) {
397+
m.Info("Image being used", "Name", sourceName, "OCID", *image.ImageId)
398+
m.OCIManagedMachinePool.Spec.NodeSourceViaImage.ImageId = image.ImageId
399+
return nil
400+
}
401+
}
402+
}
403+
}
404+
sourceJson, err := json.Marshal(response.Sources)
405+
if err != nil {
406+
return err
407+
}
408+
err = errors.New(fmt.Sprintf("could not lookup nodepool image id from nodepool options"))
409+
m.Logger.Error(err, "Could not lookup an image corresponding to the kubernetes version from OKE nodepool options",
410+
"oke-node-pool-image-sources", sourceJson)
411+
return err
412+
}
413+
414+
func isValidImage(sourceName string) bool {
415+
// invalidImageSources is the array of names of source images that should be ignored to be considered as defaults
416+
// for node pool images
417+
invalidImageSources := []string{"GPU"}
418+
for _, invalidImageSource := range invalidImageSources {
419+
if strings.Contains(sourceName, invalidImageSource) {
420+
return false
421+
}
422+
}
423+
return true
424+
}
425+
346426
func (m *ManagedMachinePoolScope) getOKENodePoolFromOCID(ctx context.Context, nodePoolId *string) (*oke.NodePool, error) {
347427
req := oke.GetNodePoolRequest{NodePoolId: nodePoolId}
348428

@@ -558,6 +638,10 @@ func (m *ManagedMachinePoolScope) UpdateNodePool(ctx context.Context, pool *oke.
558638
nodeShapeConfig.MemoryInGBs = common.Float32(float32(memoryInGBs))
559639
}
560640
}
641+
err = m.setNodepoolImageId(ctx)
642+
if err != nil {
643+
return false, err
644+
}
561645
sourceDetails := oke.NodeSourceViaImageDetails{
562646
ImageId: spec.NodeSourceViaImage.ImageId,
563647
BootVolumeSizeInGBs: spec.NodeSourceViaImage.BootVolumeSizeInGBs,

0 commit comments

Comments
 (0)