diff --git a/cmd/boot-script-service/default_api_test.go b/cmd/boot-script-service/default_api_test.go index bbdd97d..3b86a57 100644 --- a/cmd/boot-script-service/default_api_test.go +++ b/cmd/boot-script-service/default_api_test.go @@ -28,12 +28,18 @@ import ( "fmt" "net/http" "net/http/httptest" + "os" + "path/filepath" "regexp" "testing" "github.com/OpenCHAMI/bss/pkg/bssTypes" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +const testData = "testdata" + func mockGetSignedS3Url(s3Url string) (string, error) { return s3Url + "_signed", nil } @@ -311,3 +317,143 @@ func TestBootparametersPost_StoreError(t *testing.T) { status, http.StatusBadRequest) } } + +func TestBuildBootScript(t *testing.T) { + type args struct { + bd BootData + sp scriptParams + chain string + role string + subRole string + descr string + } + + tests := []struct { + desc string + expect string + err error + args args + }{ + { + // successfully generate a boot script using garbage values for all possible input fields + // this serves as an exhaustive template for new cases + desc: "generic example", + expect: "garbage_val.txt", + err: nil, + args: args{ + bd: BootData{ + Params: "bd_params", + Kernel: ImageData{ + Path: "kernel_path", + Params: "kernel_params", + }, + Initrd: ImageData{ + Path: "initrd_path", + Params: "initrd_params", + }, + CloudInit: bssTypes.CloudInit{ + MetaData: map[string]interface{}{ + "metadata_key": "metadata_val", + }, + UserData: map[string]interface{}{ + "userdata_key": "userdata_val", + }, + PhoneHome: bssTypes.PhoneHome{ + PublicKeyDSA: "phonehome_pubkeydsa", + PublicKeyRSA: "phonehome_pubkeyrsa", + PublicKeyECDSA: "phonehome_pubkeyecdsa", + PublicKeyED25519: "phonehome_pubkeyed25519", + InstanceID: "phonehome_instanceid", + Hostname: "phonehome_hostname", + FQDN: "phonehome_fqdn", + }, + }, + }, + sp: scriptParams{ + xname: "sp_xname", + nid: "sp_nid", + referralToken: "sp_rt", + }, + chain: "chain_val", + role: "role_val", + subRole: "subrole_val", + descr: "descr_val", + }, + }, + { + desc: "missing kernel path", + expect: "", + err: fmt.Errorf("busted: this host not configured for booting."), + args: args{ + descr: "busted", + bd: BootData{ + Kernel: ImageData{ + Params: "busted", + }, + }, + }, + }, + { + desc: "override ds param", + expect: "ds_override.txt", + err: nil, + args: args{ + bd: BootData{ + Params: "ds=override-example;subparam=foo", + Kernel: ImageData{ + Path: "kernel_path", + Params: "kernel_params", + }, + Initrd: ImageData{ + Path: "initrd_path", + Params: "initrd_params", + }, + CloudInit: bssTypes.CloudInit{ + MetaData: map[string]interface{}{ + "metadata_key": "metadata_val", + }, + UserData: map[string]interface{}{ + "userdata_key": "userdata_val", + }, + PhoneHome: bssTypes.PhoneHome{ + PublicKeyDSA: "phonehome_pubkeydsa", + PublicKeyRSA: "phonehome_pubkeyrsa", + PublicKeyECDSA: "phonehome_pubkeyecdsa", + PublicKeyED25519: "phonehome_pubkeyed25519", + InstanceID: "phonehome_instanceid", + Hostname: "phonehome_hostname", + FQDN: "phonehome_fqdn", + }, + }, + }, + sp: scriptParams{ + xname: "sp_xname", + nid: "sp_nid", + referralToken: "sp_rt", + }, + chain: "chain_val", + role: "role_val", + subRole: "subrole_val", + descr: "descr_val", + }, + }, + } + + for _, tt := range tests { + parent := t.Name() + t.Run(tt.desc, func(t *testing.T) { + var expect string + if tt.expect != "" { + expectBytes, err := os.ReadFile(filepath.Join(testData, parent, tt.expect)) + require.NoError(t, err) + expect = string(expectBytes) + } + + actual, err := buildBootScript(tt.args.bd, tt.args.sp, tt.args.chain, tt.args.role, tt.args.subRole, tt.args.descr) + if expect != "" { + assert.Equal(t, expect, actual) + } + assert.Equal(t, tt.err, err) + }) + } +} diff --git a/cmd/boot-script-service/testdata/TestBuildBootScript/ds_override.txt b/cmd/boot-script-service/testdata/TestBuildBootScript/ds_override.txt new file mode 100644 index 0000000..4746a8b --- /dev/null +++ b/cmd/boot-script-service/testdata/TestBuildBootScript/ds_override.txt @@ -0,0 +1,7 @@ +#!ipxe +kernel --name kernel kernel_path initrd=initrd ds=override-example;subparam=foo kernel_params xname=sp_xname nid=sp_nid bss_referral_token=sp_rt || goto boot_retry +initrd --name initrd initrd_path || goto boot_retry +boot || goto boot_retry +:boot_retry +sleep 30 +chain_val diff --git a/cmd/boot-script-service/testdata/TestBuildBootScript/garbage_val.txt b/cmd/boot-script-service/testdata/TestBuildBootScript/garbage_val.txt new file mode 100644 index 0000000..073cfe0 --- /dev/null +++ b/cmd/boot-script-service/testdata/TestBuildBootScript/garbage_val.txt @@ -0,0 +1,7 @@ +#!ipxe +kernel --name kernel kernel_path initrd=initrd bd_params kernel_params xname=sp_xname nid=sp_nid bss_referral_token=sp_rt ds=nocloud-net;s=/ || goto boot_retry +initrd --name initrd initrd_path || goto boot_retry +boot || goto boot_retry +:boot_retry +sleep 30 +chain_val diff --git a/go.mod b/go.mod index 45eced8..4a89ade 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/OpenCHAMI/bss -go 1.23 -toolchain go1.24.1 +go 1.23.0 +toolchain go1.24.2 require ( github.com/Cray-HPE/hms-base v1.15.1 @@ -28,6 +28,7 @@ require ( github.com/openchami/chi-middleware/auth v0.0.0-20240812224658-b16b83c70700 github.com/openchami/chi-middleware/log v0.0.0-20240812224658-b16b83c70700 github.com/rs/zerolog v1.33.0 + github.com/stretchr/testify v1.10.0 ) require ( @@ -37,6 +38,7 @@ require ( github.com/cenkalti/backoff/v3 v3.2.2 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-jose/go-jose/v4 v4.0.5 // indirect @@ -65,6 +67,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -83,4 +86,5 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect )