Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c8658d8
Persist custom configs during provision
rranjan3 Jun 12, 2025
3bf837e
Merge remote-tracking branch 'origin/main' into rranjan3/custom-config
rranjan3 Jun 12, 2025
80de2b1
Update comment
rranjan3 Jun 12, 2025
5d85552
Fix UT for updated inventory
rranjan3 Jun 12, 2025
6cfb0bb
Lint fix
rranjan3 Jun 12, 2025
b9a24af
Update linter config
rranjan3 Jun 12, 2025
e3c1f98
Update DKAM version to dev
rranjan3 Jun 12, 2025
7ccdef3
Make os name unique in UT
rranjan3 Jun 12, 2025
a4e84a2
Update file name pattern
rranjan3 Jun 12, 2025
3a75ccc
Update file naming
rranjan3 Jun 13, 2025
f9e4e29
Merge remote-tracking branch 'origin/main' into rranjan3/custom-config
rranjan3 Jun 13, 2025
495abb2
Bump OM version
rranjan3 Jun 13, 2025
284adb7
Bump inv version to 2.27.0
rranjan3 Jun 13, 2025
c51bc39
Merge remote-tracking branch 'origin/main' into rranjan3/custom-config
rranjan3 Jun 13, 2025
38b94a6
Merge remote-tracking branch 'origin/main' into rranjan3/custom-config
rranjan3 Jun 13, 2025
cd7afb3
Merge branch 'main' into rranjan3/custom-config
rranjan3 Jun 13, 2025
1ceb5cc
UT for wf status
rranjan3 Jun 13, 2025
42b546d
Merge remote-tracking branch 'origin/main' into rranjan3/custom-config
rranjan3 Jun 13, 2025
4fc5bb1
Merge branch 'rranjan3/custom-config' of https://github.com/open-edge…
rranjan3 Jun 16, 2025
b119f97
Refactor ConcatMapValuesSorted
rranjan3 Jun 16, 2025
1131e95
Update field description
rranjan3 Jun 16, 2025
9fa2c78
Merge remote-tracking branch 'origin/main' into rranjan3/custom-config
rranjan3 Jun 20, 2025
95be60a
Review: Record todo for custom tinker action
rranjan3 Jun 23, 2025
7959f5e
Use ConcatMapValuesSorted from inventory
rranjan3 Jun 24, 2025
5712c2f
Merge branch 'main' into rranjan3/custom-config
sys-orch Jun 26, 2025
516e1bf
Add merge_how to infra.cfg
rranjan3 Jun 27, 2025
174573d
Refactor infra.cfg
rranjan3 Jun 30, 2025
540a61a
Fix UTs & make merge_how one-liner
rranjan3 Jul 1, 2025
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
2 changes: 1 addition & 1 deletion dkam/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ issues:
- Error return value of `.*Write` is not checked
- Error return value of `.*Stop` is not checked
exclude-rules:
uniq-by-line: false

output:
formats: colored-line-number:stdout,html:out/golangci-lint_report.html
print-linter-name: true
uniq-by-line: false
sort-results: true
2 changes: 1 addition & 1 deletion dkam/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.31.1
1.31.2-dev
2 changes: 1 addition & 1 deletion onboarding-manager/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ issues:
- Error return value of `.*Write` is not checked
- Error return value of `.*Stop` is not checked
exclude-rules:
uniq-by-line: false
output:
formats: colored-line-number:stdout,html:out/golangci-lint_report.html
print-linter-name: true
uniq-by-line: false
sort-results: true
2 changes: 1 addition & 1 deletion onboarding-manager/REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ path = [

"**.md",
"pkg/cloudinit/testout/*",
"pkg/cloudinit/infra.cfg",
"pkg/cloudinit/99_infra.cfg",
"api/buf.lock",
"pkg/api/onboardingmgr/v1/*.pb.*go"
]
Expand Down
2 changes: 1 addition & 1 deletion onboarding-manager/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.37.1
1.37.2
2 changes: 1 addition & 1 deletion onboarding-manager/docs/cloud-init-os-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This document provides guidance on how to ensure compatibility with cloud-init w

# Overview of Edge Infrastructure Manager cloud-init

The [inframanager cloud-init](./../pkg/cloudinit/infra.cfg) is intended to be an OS-independent mechanism that is limited to providing a Day0/Day1 configuration for Edge Nodes.
The [inframanager cloud-init](./../pkg/cloudinit/99_infra.cfg) is intended to be an OS-independent mechanism that is limited to providing a Day0/Day1 configuration for Edge Nodes.

It is worth noting that the goal of cloud-init should be to provide a static configuration files or perform OS configurations that are self-contained and don't require network connectivity. Any more advanced steps should be performed by the [platform bundle script](./../platform-bundle/README.md).

Expand Down
2 changes: 1 addition & 1 deletion onboarding-manager/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ go 1.24.4
require (
github.com/envoyproxy/protoc-gen-validate v1.2.1
github.com/google/uuid v1.6.0
github.com/open-edge-platform/infra-core/inventory/v2 v2.26.3-0.20250611095359-3d196af3ec71
github.com/open-edge-platform/infra-core/inventory/v2 v2.28.0
github.com/open-edge-platform/infra-onboarding/dkam v1.29.0
github.com/open-edge-platform/orch-library/go v0.6.1
github.com/pkg/errors v0.9.1
Expand Down
4 changes: 2 additions & 2 deletions onboarding-manager/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/open-edge-platform/infra-core/inventory/v2 v2.26.3-0.20250611095359-3d196af3ec71 h1:E1Fl/lri5JGzMXXvJ0woJL4F5Q3LJ7kFCdQ4En9uGrE=
github.com/open-edge-platform/infra-core/inventory/v2 v2.26.3-0.20250611095359-3d196af3ec71/go.mod h1:/bg3cDaZgXU88DOzGLJSkbK4ETpwibhmJnhkpvid7v0=
github.com/open-edge-platform/infra-core/inventory/v2 v2.28.0 h1:/mC9U9z33TrGAVyVKllQcCEh27aJRVzq732jXSigv1Q=
github.com/open-edge-platform/infra-core/inventory/v2 v2.28.0/go.mod h1:8B/tr37uweQz+FVU23VzKRcQGfJKuS+0dLwYmdP5oJY=
github.com/open-edge-platform/infra-onboarding/dkam v1.29.0 h1:rmEIXqoA3CZWhMT0BvAMdGcG1q7P9J1OWsspmM8EBVA=
github.com/open-edge-platform/infra-onboarding/dkam v1.29.0/go.mod h1:bJQ+0ylXYg9KP04a2RV9AKRGULvTosqe7vouCYQXYaw=
github.com/open-edge-platform/orch-library/go v0.6.1 h1:IGR2ic73f3obnhlxTRfHcyYMbPbYu7BSqa9UYyEZ78Q=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func createOsWithArgs(tb testing.TB, doCleanup bool,
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
osr = &osv1.OperatingSystemResource{
Name: "for unit testing purposes",
Name: "test-os-" + getFirstNChars(getMD5Hash(fmt.Sprintf("%d", time.Now().UnixNano())), 8),
UpdateSources: []string{"test entries"},
ImageUrl: "example.raw.gz",
ProfileName: inv_testing.GenerateRandomProfileName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1996,7 +1996,7 @@ func TestInteractiveOnboardingService_startZeroTouch_OSSecurityFeatureEnable(t *

// Create Host and OS resources
host := inv_testing.CreateHost(t, nil, nil)
osRes := inv_testing.CreateOsWithArgs(t, "", "profile:profile",
osRes := inv_testing.CreateOsWithArgs(t, "", "", "profile:profile",
osv1.SecurityFeature_SECURITY_FEATURE_SECURE_BOOT_AND_FULL_DISK_ENCRYPTION, osv1.OsType_OS_TYPE_MUTABLE)
dao := inv_testing.NewInvResourceDAOOrFail(t)

Expand Down
3 changes: 3 additions & 0 deletions onboarding-manager/internal/onboarding/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ type (
SSHKey string
// OS resource ID
OSResourceID string
// CustomConfigs is a map name->config where name is unique in the CustomConfigResource
// and config is a string with the content of the custom cloud init config.
CustomConfigs map[string]string
// IsStandaloneNode indicates whether EN should be provisioned as a standalone node
IsStandaloneNode bool
}
Expand Down
7 changes: 7 additions & 0 deletions onboarding-manager/internal/onboarding/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ func runProdWorkflow(
deviceInfo.SSHKey = instance.GetLocalaccount().SshKey
}

if len(instance.CustomConfig) != 0 {
deviceInfo.CustomConfigs = make(map[string]string)
for _, customCfg := range instance.CustomConfig {
deviceInfo.CustomConfigs[customCfg.Name] = customCfg.Config
}
}

templateName, found := templates.OSTypeToTemplateName[deviceInfo.OsType]
if !found {
return inv_errors.Errorf("Cannot find Tinkerbell template for OS type %s", deviceInfo.OsType)
Expand Down
33 changes: 33 additions & 0 deletions onboarding-manager/internal/onboarding/workflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,39 @@ type handleWorkflowTestCase struct {
wantErr bool
}

func Test_handleWorkflowStatus_withCustomConfigsActions(t *testing.T) {
instance := &computev1.InstanceResource{
Host: &computev1.HostResource{
ResourceId: "host-084d9b08",
Uuid: uuid.NewString(),
},
}
workflow := &tink.Workflow{
Status: tink.WorkflowStatus{
State: tink.WorkflowStateRunning,
Tasks: []tink.Task{
{
Actions: []tink.Action{
{Name: "custom-configs", Status: tink.WorkflowStateSuccess},
{Name: "custom-configs-split", Status: tink.WorkflowStateRunning},
},
},
},
},
Spec: tink.WorkflowSpec{
HardwareMap: map[string]string{
"DeviceInfoOSResourceID": "os-12345678",
},
},
}
onSuccess := inv_status.New("Provisioned", statusv1.StatusIndication_STATUS_INDICATION_IDLE)
onFailure := inv_status.New("Provisioning Failed", statusv1.StatusIndication_STATUS_INDICATION_ERROR)

err := handleWorkflowStatus(instance, workflow, onSuccess, onFailure)
assert.ErrorContains(t, err, "") // Should be in progress, so error is returned
assert.Equal(t, instance.ProvisioningStatus, "Provisioning In Progress: 2/2: Installing custom cloud-init configs")
}

func createTestCase(name string, workflowState tink.WorkflowState, expectedStatus string, wantErr bool) handleWorkflowTestCase {
return handleWorkflowTestCase{
name: name,
Expand Down
6 changes: 5 additions & 1 deletion onboarding-manager/internal/tinkerbell/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ var WorkflowStepToStatusDetail = map[string]string{
ActionSystemConfiguration: "Applying system configuration",
ActionKernelupgrade: "Upgrading kernel",
ActionCloudInitInstall: "Installing cloud-init",
ActionCloudinitDsidentity: "Setting up cloud-init",
// FIXME : Restrict to single action which does a mass copy.
// Scaling becomes a challenge with growing number of actions ITEP-70669
ActionCustomConfigInstall: "Copying custom cloud-init configs",
ActionCustomConfigSplit: "Installing custom cloud-init configs",
ActionCloudinitDsidentity: "Setting up cloud-init",
}

func GenerateStatusDetailFromWorkflowState(workflow *tink.Workflow) string {
Expand Down
10 changes: 10 additions & 0 deletions onboarding-manager/internal/tinkerbell/template_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strconv"

osv1 "github.com/open-edge-platform/infra-core/inventory/v2/pkg/api/os/v1"
"github.com/open-edge-platform/infra-core/inventory/v2/pkg/util/collections"
"github.com/open-edge-platform/infra-onboarding/dkam/pkg/config"
"github.com/open-edge-platform/infra-onboarding/onboarding-manager/internal/env"
onboarding_types "github.com/open-edge-platform/infra-onboarding/onboarding-manager/internal/onboarding/types"
Expand All @@ -26,6 +27,8 @@ const (
ActionStreamOSImage = "stream-os-image"
ActionCloudInitInstall = "install-cloud-init"
ActionSystemConfiguration = "system-configuration"
ActionCustomConfigInstall = "custom-configs"
ActionCustomConfigSplit = "custom-configs-split"
ActionInstallScript = "service-script-for-profile-pkg-and-node-agents-install"
ActionEfibootset = "efibootset-for-diskboot"
ActionFdeEncryption = "fde-encryption"
Expand Down Expand Up @@ -70,6 +73,10 @@ const (
tinkerActionImage2Disk = "image2disk"
tinkerActionWritefile = "writefile"
tinkerActionSecurebootflag = "securebootflag"

// Use a delimiter that is highly unlikely to appear in any config or script.
// ASCII Unit Separator (0x1F) is a safe choice.
customConfigDelimiter = "\x1F"
)

type TinkerActionImages struct {
Expand All @@ -95,6 +102,7 @@ type WorkflowInputs struct {
DeviceInfo onboarding_types.DeviceInfo
TinkerActionImage TinkerActionImages
CloudInitData string
CustomConfigs string
InstallerScript string
// OsResourceID resource ID of Operating System that was specified initially at the provisioning time
OsResourceID string
Expand Down Expand Up @@ -319,6 +327,8 @@ func GenerateWorkflowInputs(ctx context.Context, deviceInfo onboarding_types.Dev

inputs.InstallerScript = strconv.Quote(installerScript)
inputs.CloudInitData = strconv.Quote(cloudInitData)
inputs.CustomConfigs = strconv.Quote(collections.ConcatMapValuesSorted(deviceInfo.CustomConfigs, customConfigDelimiter))

inputs.Env = Env{
ENProxyHTTP: infraConfig.ENProxyHTTP,
ENProxyHTTPS: infraConfig.ENProxyHTTPS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,38 @@ tasks:
timeout: 90
environment:
FS_TYPE: ext4
DEST_PATH: /etc/cloud/cloud.cfg.d/infra.cfg
DEST_PATH: /etc/cloud/cloud.cfg.d/99_infra.cfg
UID: 0
GID: 0
MODE: "0755"
DIRMODE: "0755"
CONTENTS: {{ .CloudInitData }}
{{- if gt (len .CustomConfigs) 0 }}
- name: "custom-configs"
image: {{ .TinkerActionImageWriteFile }}
timeout: 90
environment:
FS_TYPE: ext4
DEST_PATH: /etc/cloud/cloud.cfg.d/custom.cfg
UID: 0
GID: 0
MODE: "0755"
DIRMODE: "0755"
CONTENTS: {{ .CustomConfigs }}
- name: "custom-configs-split"
image: {{ .TinkerActionImageCexec }}
timeout: 200
environment:
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: |
awk -v RS='\x1F' 'BEGIN{i=0} {
fn=sprintf("/etc/cloud/cloud.cfg.d/%02d_infra.cfg", i++);
print > fn; close(fn); system("chmod 755 " fn)
}' /etc/cloud/cloud.cfg.d/custom.cfg &&
rm -f /etc/cloud/cloud.cfg.d/custom.cfg
{{- end }}
- name: "cloud-init-ds-identity"
image: {{ .TinkerActionImageWriteFile }}
timeout: 90
Expand Down
28 changes: 27 additions & 1 deletion onboarding-manager/internal/tinkerbell/templates/ubuntu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,38 @@ tasks:
timeout: 90
environment:
FS_TYPE: ext4
DEST_PATH: /etc/cloud/cloud.cfg.d/infra.cfg
DEST_PATH: /etc/cloud/cloud.cfg.d/99_infra.cfg
UID: 0
GID: 0
MODE: "0755"
DIRMODE: "0755"
CONTENTS: {{ .CloudInitData }}
{{- if gt (len .CustomConfigs) 0 }}
- name: "custom-configs"
image: {{ .TinkerActionImageWriteFile }}
timeout: 90
environment:
FS_TYPE: ext4
DEST_PATH: /etc/cloud/cloud.cfg.d/custom.cfg
UID: 0
GID: 0
MODE: "0755"
DIRMODE: "0755"
CONTENTS: {{ .CustomConfigs }}
- name: "custom-configs-split"
image: {{ .TinkerActionImageCexec }}
timeout: 200
environment:
FS_TYPE: ext4
CHROOT: y
DEFAULT_INTERPRETER: "/bin/sh -c"
CMD_LINE: |
awk -v RS='\x1F' 'BEGIN{i=0} {
fn=sprintf("/etc/cloud/cloud.cfg.d/%02d_infra.cfg", i++);
print > fn; close(fn); system("chmod 755 " fn)
}' /etc/cloud/cloud.cfg.d/custom.cfg &&
rm -f /etc/cloud/cloud.cfg.d/custom.cfg
{{- end }}
- name: "cloud-init-ds-identity"
image: {{ .TinkerActionImageWriteFile }}
timeout: 90
Expand Down
Loading