@@ -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