cos-customizer: Add -machine-type flag
This new flag allows users to select the machine type of the preload VM.
BUG=b/176990931
TEST=./run_tests.sh
Change-Id: I9e514e6e0eced8bf981067d3779c26369ea7574a
Reviewed-on: https://cos-review.googlesource.com/c/cos/tools/+/26021
Cloud-Build: GCB Service account <228075978874@cloudbuild.gserviceaccount.com>
Tested-by: Robert Kolchmeyer <rkolchmeyer@google.com>
Reviewed-by: Roy Yang <royyang@google.com>
diff --git a/src/cmd/cos_customizer/README.md b/src/cmd/cos_customizer/README.md
index 821177a..f4b51ee 100644
--- a/src/cmd/cos_customizer/README.md
+++ b/src/cmd/cos_customizer/README.md
@@ -259,6 +259,11 @@
overall Cloud Build workflow timeout expires, the task will be cancelled without
any opportunity to clean up resources.
+`-machine-type`: The machine type to use for the COS Customizer preload VM.
+Defaults to `n1-standard-1`. Useful for optimizing costs. Note that this is
+separate from the Cloud Build machine type option, which sets the machine type
+of the Cloud Build VM, which is different from the COS Customizer preload VM.
+
An example `finish-image-build` step looks like the following:
- name: 'gcr.io/cos-cloud/cos-customizer'
diff --git a/src/cmd/cos_customizer/finish_image_build.go b/src/cmd/cos_customizer/finish_image_build.go
index 1707bac..e69870b 100644
--- a/src/cmd/cos_customizer/finish_image_build.go
+++ b/src/cmd/cos_customizer/finish_image_build.go
@@ -41,6 +41,7 @@
imageProject string
zone string
project string
+ machineType string
imageName string
imageSuffix string
imageFamily string
@@ -86,6 +87,7 @@
"the deleted state).")
flags.StringVar(&f.zone, "zone", "", "Zone to make GCE resources in.")
flags.StringVar(&f.project, "project", "", "Project to make GCE resources in.")
+ flags.StringVar(&f.machineType, "machine-type", "n1-standard-1", "Machine type to use during the build.")
if f.labels == nil {
f.labels = newMapVar()
}
@@ -153,6 +155,7 @@
}
buildConfig.Project = f.project
buildConfig.Zone = f.zone
+ buildConfig.MachineType = f.machineType
buildConfig.DiskSize = f.diskSize
buildConfig.Timeout = f.timeout.String()
provConfig := &provisioner.Config{}
diff --git a/src/data/build_image.wf.json b/src/data/build_image.wf.json
index 7329148..8b280ae 100644
--- a/src/data/build_image.wf.json
+++ b/src/data/build_image.wf.json
@@ -7,7 +7,8 @@
"output_image_project": {"Required": true, "Description": "Project of output image."},
"cidata_img": {"Required": true, "Description": "Path to CIDATA vfat image containing cloud-init user-data and the provisioner program. Must be in .tar.gz format."},
"disk_size_gb": {"Value": "10", "Description": "The disk size to use for preloading."},
- "host_maintenance": {"Value": "MIGRATE", "Description": "VM behavior when there is maintenance."}
+ "host_maintenance": {"Value": "MIGRATE", "Description": "VM behavior when there is maintenance."},
+ "machine_type": {"Required": true, "Description": "Machine type of the preload VM."}
},
"Sources": {
"cloud-config": "/data/startup.yaml",
@@ -50,6 +51,7 @@
{
"Name": "preload-vm",
"Disks": [{"Source": "boot-disk"}, {"Source": "cidata-disk"}],
+ "MachineType": "${machine_type}",
"guestAccelerators": {{.Accelerators}},
"scheduling": {
"onHostMaintenance": "${host_maintenance}"
diff --git a/src/pkg/config/config.go b/src/pkg/config/config.go
index d680a28..498882b 100644
--- a/src/pkg/config/config.go
+++ b/src/pkg/config/config.go
@@ -66,6 +66,7 @@
GCSDir string
Project string
Zone string
+ MachineType string
DiskSize int
GPUType string
Timeout string
diff --git a/src/pkg/preloader/preload.go b/src/pkg/preloader/preload.go
index e5aa5ab..f135031 100644
--- a/src/pkg/preloader/preload.go
+++ b/src/pkg/preloader/preload.go
@@ -306,6 +306,8 @@
output.Project,
"-var:cidata_img",
ciDataFile,
+ "-var:machine_type",
+ buildSpec.MachineType,
"-var:host_maintenance",
hostMaintenance,
"-gcs_path",
diff --git a/src/pkg/preloader/preload_test.go b/src/pkg/preloader/preload_test.go
index c6e015f..09510e7 100644
--- a/src/pkg/preloader/preload_test.go
+++ b/src/pkg/preloader/preload_test.go
@@ -344,6 +344,13 @@
want: []string{"-zone", "zone"},
},
{
+ testName: "MachineType",
+ inputImage: config.NewImage("", ""),
+ outputImage: config.NewImage("", ""),
+ buildConfig: &config.Build{MachineType: "n1-standard-1", GCSBucket: "bucket", GCSDir: "dir"},
+ want: []string{"-var:machine_type", "n1-standard-1"},
+ },
+ {
testName: "Timeout",
inputImage: config.NewImage("", ""),
outputImage: config.NewImage("", ""),
diff --git a/testing/machine_type_test.yaml b/testing/machine_type_test.yaml
new file mode 100644
index 0000000..a230666
--- /dev/null
+++ b/testing/machine_type_test.yaml
@@ -0,0 +1,45 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the License);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+substitutions:
+ "_TEST": "machine_type_test"
+ "_INPUT_IMAGE": "cos-dev-69-10895-0-0"
+ "_INPUT_PROJECT": "cos-cloud"
+steps:
+- name: "gcr.io/cloud-builders/bazel"
+ args: ["run", "--spawn_strategy=standalone", ":cos_customizer", "--", "--norun"]
+- name: "bazel:cos_customizer"
+ args: ["start-image-build",
+ "-build-context=testing/${_TEST}",
+ "-image-name=${_INPUT_IMAGE}",
+ "-image-project=${_INPUT_PROJECT}",
+ "-gcs-bucket=${PROJECT_ID}_cloudbuild",
+ "-gcs-workdir=customizer-$BUILD_ID"]
+- name: "bazel:cos_customizer"
+ args: ["run-script",
+ "-script=preload.sh"]
+- name: "bazel:cos_customizer"
+ args: ["finish-image-build",
+ "-machine-type=n1-standard-8",
+ "-zone=us-west1-b",
+ "-project=$PROJECT_ID",
+ "-image-name=preload-test-$BUILD_ID",
+ "-image-project=$PROJECT_ID"]
+- name: "gcr.io/compute-image-tools/daisy"
+ args: ["-project=$PROJECT_ID", "-zone=us-west1-b", "-var:image_name",
+ "preload-test-$BUILD_ID", "-var:image_project", "$PROJECT_ID",
+ "-var:test_cfg", "../${_TEST}/preload_test.cfg", "testing/util/run_test.wf.json"]
+options:
+ machineType: "N1_HIGHCPU_8"
+timeout: "7200s"
diff --git a/testing/machine_type_test/preload.sh b/testing/machine_type_test/preload.sh
new file mode 100644
index 0000000..840e0ad
--- /dev/null
+++ b/testing/machine_type_test/preload.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+nproc > /var/lib/nproc
diff --git a/testing/machine_type_test/preload_test.cfg b/testing/machine_type_test/preload_test.cfg
new file mode 100644
index 0000000..3359ed6
--- /dev/null
+++ b/testing/machine_type_test/preload_test.cfg
@@ -0,0 +1,79 @@
+#cloud-config
+#
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+write_files:
+ - path: /tmp/preloader-test/test.sh
+ permissions: 0644
+ owner: root
+ content: |
+ set -o errexit
+ set -o pipefail
+
+ trap 'fail exiting due to errors' EXIT
+
+ fail() {
+ echo "TestFail: $@"
+ }
+
+ testNproc() {
+ if [[ ! -f "/var/lib/nproc" ]]; then
+ echo "/var/lib/nproc is missing"
+ echo "testNproc fail"
+ RESULT="fail"
+ return
+ fi
+ if [[ "$(cat "/var/lib/nproc")" != "8" ]]; then
+ echo "/var/lib/nproc: got $(cat "/var/lib/nproc"), want 8"
+ echo "testNproc fail"
+ RESULT="fail"
+ return
+ fi
+ echo "testNproc pass"
+ }
+
+ main() {
+ RESULT="pass"
+ testNproc
+ if [[ "${RESULT}" == "fail" ]]; then
+ exit 1
+ fi
+ }
+
+ main 2>&1 | sed "s/^/TestStatus: /"
+ trap - EXIT
+ echo "TestPass: all tests passed"
+
+ - path: /etc/systemd/system/preloader-test.service
+ permissions: 0644
+ owner: root
+ content: |
+ [Unit]
+ Description=Preloader test
+ Wants=network-online.target gcr-online.target docker.service
+ After=network-online.target gcr-online.target docker.service
+
+ [Service]
+ Type=oneshot
+ RemainAfterExit=yes
+ User=root
+ ExecStart=/bin/bash /tmp/preloader-test/test.sh
+ StandardOutput=tty
+ StandardError=tty
+ TTYPath=/dev/ttyS1
+
+runcmd:
+ - systemctl daemon-reload
+ - systemctl --no-block start preloader-test.service