Skip to content

Commit 05663a8

Browse files
committed
libcloud: build and replicate aws-winli images for supported streams
Expand the replicate to clouds functionality to build AWS Windows License Included (winli) images for streams that support it before replicating AMIs to other regions. `cosa aws-replicate` will now replicate both traditional AMIs and aws-winli AMIs if present in the metadata. See: coreos/coreos-assembler#4069 Also add `create_and_replicate_winli_ami` as a stream level knob to the pipeline config to enable building and replicating the AMIs for specific streams.
1 parent 8761827 commit 05663a8

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

docs/config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ streams:
119119
# When mechanical streams have `scheduled` on, then
120120
# `build-mechanical` will only build those streams
121121
scheduled: true
122+
# OPTIONAL: Create and replicate AWS Windows License Included images for this stream.
123+
create_and_replicate_winli_ami: true
122124

123125
# REQUIRED: architectures to build for other than x86_64
124126
additional_arches: [aarch64, ppc64le, s390x]

libcloud.groovy

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ def replicate_to_clouds(pipecfg, basearch, buildID, stream) {
66
cosa meta --build=${buildID} --arch=${basearch} --dump
77
"""))
88
def replicators = [:]
9+
def builders = [:]
910
def credentials
11+
def stream_info = pipecfg.streams[stream]
1012

1113
credentials = [file(variable: "ALIYUN_IMAGE_UPLOAD_CONFIG",
1214
credentialsId: "aliyun-image-upload-config")]
@@ -46,10 +48,81 @@ def replicate_to_clouds(pipecfg, basearch, buildID, stream) {
4648
""")
4749
}
4850
}
51+
// A closure to build the aws-winli AMI. This will be called before replicating to
52+
// all regions, if the option is set for the current stream. `cosa aws-replicate`
53+
// will handle both traditional AMIs and aws-winli AMIs if present in the metadata.
54+
// aws-winli is only supported on x86_64.
55+
def awsWinLIBuildClosure = { config, credentialId ->
56+
def creds = [file(variable: "AWS_CONFIG_FILE", credentialsId: credentialId)]
57+
withCredentials(creds) {
58+
utils.syncCredentialsIfInRemoteSession(["AWS_CONFIG_FILE"])
59+
def c = config
60+
// In 4.19+ we switched the command to upload to clouds to
61+
// `cosa imageupload-<cloud>`
62+
// https://github.com/coreos/coreos-assembler/pull/4074
63+
def image_upload_cmd = "imageupload"
64+
65+
// Discover the latest Windows Server AMI to use as the winli-builder instance.
66+
// The AMI rotates frequently with Windows updates and is not persistant in AWS
67+
// for very long, so we need to find the most recent AMI ID.
68+
// Windows Server 2022 was selected here because the Windows Server 2025 AMI does
69+
// not allow legacy bios. WS2022 has an EOL date of 2026-10-13.
70+
// https://learn.microsoft.com/en-us/lifecycle/products/windows-server-2022
71+
// If WS2022 becomes inaccessible in the future and we still need BIOS for our
72+
// winli images then we can just use one of our own previously created winli
73+
// images and pass that to `--windows-ami` below.
74+
def windows_server_ami_name = ""
75+
windows_server_ami_name = "Windows_Server-2022-English-Full-Base-*"
76+
def windows_server_ami = shwrapCapture("""
77+
aws ec2 describe-images \
78+
--region=${c.primary_region} \
79+
--owners="amazon" \
80+
--filters="Name=name,Values=${windows_server_ami_name}" \
81+
--query="sort_by(Images, &CreationDate)[-1].ImageId" \
82+
--output text
83+
""")
84+
85+
// validate that we did actually get an AMI ID returned.
86+
if (!(windows_server_ami_name != /^ami-[0-9][a-f]{17}$/)) {
87+
error("Invalid Windows Server AMI ID: ${windows_server_ami}")
88+
}
89+
90+
def extraArgs = []
91+
if (c.grant_users) {
92+
extraArgs += c.grant_users.collect{"--grant-user=${it}"}
93+
extraArgs += c.grant_users.collect{"--grant-user-snapshot=${it}"}
94+
}
95+
if (c.tags) {
96+
extraArgs += c.tags.collect { "--tags=${it}" }
97+
}
98+
if (c.public) {
99+
extraArgs += "--public"
100+
}
101+
shwrap("""
102+
cosa ${image_upload_cmd}-aws \
103+
--upload \
104+
--winli \
105+
--windows-ami=${windows_server_ami} \
106+
--arch=${basearch} \
107+
--build=${buildID} \
108+
--region=${c.primary_region} \
109+
--credentials-file=\${AWS_CONFIG_FILE} \
110+
${extraArgs.join(' ')}
111+
""")
112+
}
113+
}
49114
if (meta.amis) {
50115
credentials = [file(variable: "UNUSED", credentialsId: "aws-build-upload-config")]
51116
if (pipecfg.clouds?.aws &&
52117
utils.credentialsExist(credentials)) {
118+
119+
// aws-winli is only supported on x86_64
120+
if ((basearch == "x86_64") && (stream_info.create_and_replicate_winli_ami)) {
121+
builders["☁️ 🔨:aws-winli"] = {
122+
awsWinLIBuildClosure.call(pipecfg.clouds.aws,
123+
"aws-build-upload-config")
124+
}
125+
}
53126
replicators["☁️ 🔄:aws"] = {
54127
awsReplicateClosure.call(pipecfg.clouds.aws,
55128
"aws-build-upload-config")
@@ -92,6 +165,7 @@ def replicate_to_clouds(pipecfg, basearch, buildID, stream) {
92165
}
93166
}
94167

168+
parallel builders
95169
parallel replicators
96170
}
97171
// Upload artifacts to clouds

0 commit comments

Comments
 (0)