Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions internal/controllers/resources/init_containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,26 @@ func (f *PodFactory) copyWekaVersionToContainer(pod *v1.Pod) {
Command: []string{"sh", "-c"},
Args: []string{
`
# Copy the actual binary file that command resolves to (follows symlinks)
mkdir -p /shared-weka-version/cli &&
cp -a -- "$(readlink -f -- "$(command -v weka)")" /shared-weka-version/cli/weka &&
echo "copy-cli init container done"
# Stage the weka CLI outside /opt/weka: the extraction step below bind-mounts
# over /opt/weka, where the CLI lives, and would otherwise hide it.
mkdir -p /shared-weka-version/cli || exit 1
# the wekactl filename carries a per-image hash and the machine arch
ARCH=$(uname -m)
CLI=$(ls -1 /opt/weka/dist/image/wekactl-*-"$ARCH" 2>/dev/null | head -1)
if [ -z "$CLI" ]; then
# older images ship only the weka binary; resolve the path we shadow
# rather than PATH, so a wrapper script can never be staged onto the
# very path it delegates to
CLI=$(readlink -f -- /usr/bin/weka)
fi
if [ -z "$CLI" ] || [ ! -f "$CLI" ]; then
echo "ERROR: no weka CLI found to stage" >&2
exit 1
fi
cp -- "$CLI" /shared-weka-version/cli/weka || exit 1
# the source is not executable in the image, so set the bit explicitly
chmod 0755 /shared-weka-version/cli/weka || exit 1
echo "copy-cli init container done: staged $CLI"
`,
},
VolumeMounts: []v1.VolumeMount{
Expand Down Expand Up @@ -148,6 +164,13 @@ func (f *PodFactory) copyWekaVersionToContainer(pod *v1.Pod) {
Name: sharedVolumeName,
MountPath: sharedVolumeMountPath,
})
// the wrapper at /usr/local/bin/weka execs /usr/bin/weka, so shadowing that path makes the
// container use the CLI staged from the cluster image instead of its own older one
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, v1.VolumeMount{
Name: sharedVolumeName,
MountPath: "/usr/bin/weka",
SubPath: "cli/weka",
})
pod.Spec.Volumes = append(pod.Spec.Volumes, v1.Volume{
Name: sharedVolumeName,
VolumeSource: v1.VolumeSource{
Expand Down
7 changes: 6 additions & 1 deletion internal/controllers/wekacontainer/funcs_pod_ensure.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,14 @@ func (r *containerReconcilerLoop) ensurePod(ctx context.Context) error {
image = drivers.GetBuilderImageForNode(node)
}

builderFlags, ffErr := r.GetFeatureFlags(ctx)
if ffErr != nil {
return errors.Wrap(ffErr, "failed to get feature flags for drivers-builder")
}

payloadBytes, _ := json.Marshal(map[string]string{ //nolint:errcheck // error return value intentionally not checked
"targetImage": container.Spec.Image,
"cliImage": image,
"cliImage": drivers.GetBuilderCliImage(builderFlags, container.Spec.Image, image),
})
container.Spec.Instructions = &weka.Instructions{
Type: weka.InstructionCopyWekaFilesToDriverLoader,
Expand Down
35 changes: 23 additions & 12 deletions internal/drivers/drivers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,25 @@ import (
"strings"

"github.com/weka/weka-operator/internal/config"
"github.com/weka/weka-operator/internal/pkg/domain"
"github.com/weka/weka-operator/internal/services"
v1 "k8s.io/api/core/v1"
)

var (
ubuntuRe = regexp.MustCompile(`(?i)ubuntu\s+(\d+)\.(\d+)`)
rhelRe = regexp.MustCompile(`(?i)rhel\s*(\d+)`)
rockyRe = regexp.MustCompile(`(?i)rocky\s*(\d+)`)
rhelRe = regexp.MustCompile(`(?i)(?:rhel|red\s+hat\s+enterprise\s+linux)\s*(\d+)`)
rockyRe = regexp.MustCompile(`(?i)rocky(?:\s+linux)?\s*(\d+)`)
)

// NormalizeOSImageName converts OS image names into short, DNS-1123 compliant canonical IDs.
// Examples:
//
// "Ubuntu 22.04.5 LTS" -> "ubuntu-22-04"
// "Ubuntu 24.04.3 LTS" -> "ubuntu-24"
// "RHEL 9.4" -> "rhel09"
// "Rocky Linux 8.10" -> "rocky08"
// "Ubuntu 22.04.5 LTS" -> "ubuntu-22-04"
// "Ubuntu 24.04.3 LTS" -> "ubuntu-24"
// "RHEL 9.4" -> "rhel09"
// "Red Hat Enterprise Linux 9.7 (Plow)" -> "rhel09"
// "Rocky Linux 8.10" -> "rocky08"
func NormalizeOSImageName(input string) string {
s := strings.TrimSpace(input)

Expand Down Expand Up @@ -65,13 +67,22 @@ func GetBuilderImageForNode(node *v1.Node) string {

func GetLoaderImageForNode(ctx context.Context, node *v1.Node, image string) string {
flags, err := services.GetFeatureFlags(ctx, image)
if err == nil && flags != nil {
if err != nil {
flags = nil
}

return GetBuilderCliImage(flags, image, GetBuilderImageForNode(node))
}

// GetBuilderCliImage picks the image that supplies the weka CLI staged for the
// drivers-builder init containers. The extraction step bind-mounts over /opt/weka,
// where the cluster image keeps its CLI, so a CLI is always staged out of band;
// prefer the cluster image's own CLI when it can copy driver files itself.
func GetBuilderCliImage(flags *domain.FeatureFlags, clusterImage, builderImage string) string {
if flags != nil && flags.WekaGetCopyLocalDriverFiles {
// innovation cli --kernel-build-id etc.
if flags.WekaGetCopyLocalDriverFiles {
return image
}
return clusterImage
}

// else - can use the builder image that has "innovation" cli
return GetBuilderImageForNode(node)
return builderImage
}
27 changes: 27 additions & 0 deletions internal/drivers/drivers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,33 @@ var _ = AfterSuite(func() {
}
})

func TestNormalizeOSImageName(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{"Ubuntu 22.04.5 LTS", "Ubuntu 22.04.5 LTS", "ubuntu-22-04"},
{"Ubuntu 24.04.3 LTS", "Ubuntu 24.04.3 LTS", "ubuntu-24"},
{"Ubuntu 24.04.4 LTS", "Ubuntu 24.04.4 LTS", "ubuntu-24"},
{"RHEL 9.4", "RHEL 9.4", "rhel09"},
{"Red Hat Enterprise Linux 9.7 (Plow)", "Red Hat Enterprise Linux 9.7 (Plow)", "rhel09"},
{"Red Hat Enterprise Linux 8.10", "Red Hat Enterprise Linux 8.10", "rhel08"},
{"Rocky Linux 8.10", "Rocky Linux 8.10", "rocky08"},
{"empty string", "", "unknown-os"},
{"Some Weird Distro 1.2", "Some Weird Distro 1.2", "unknown-os"},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := NormalizeOSImageName(tt.input)
if got != tt.want {
t.Errorf("NormalizeOSImageName(%q) = %q, want %q", tt.input, got, tt.want)
}
})
}
}

var _ = Describe("Driver Image Selection", func() {

BeforeEach(func() {
Expand Down
Loading