Finish upload job

This fixes some minor issues with the upload job and removes the
temporary testing settings.

It also configures the job so that if a secret is provided, it will
upload the image, but if the secret is omitted, it will only build it.

We omit the secret in check, and provide it in gate.  In the future,
we will provide it on the dedicated image build pipelines.

Change-Id: I17e519a6282e700fd09ce16c95bf58ef092b9dc6
This commit is contained in:
James E. Blair 2024-10-03 13:32:10 -07:00
parent 24be1f3b72
commit 91a3c71eef
9 changed files with 16 additions and 146 deletions

View File

@ -1,19 +1,9 @@
- hosts: localhost
- hosts: all
tasks:
- name: Upload image
when: image_upload_secret is defined
no_log: true
with_items: '{{ build_diskimage_formats }}'
loop_control:
loop_var: upload_image_format
include_role:
name: image-upload-swift
vars:
cloud:
auth_type: 'v3applicationcredential'
auth:
auth_url: 'https://keystone.api.sjc3.rackspacecloud.com/v3'
application_credential_id: '{{ image_upload_secret.application_credential_id }}'
application_credential_secret: '{{ image_upload_secret.application_credential_secret }}'
user_domain_name: rackspace_cloud_domain
container: images-a3d39eaeea5f
filename: '{{ ansible_user_dir }}/dib-images/{{ build_diskimage_image_name }}/{{ upload_image_format }}'
command: swift --os-auth-url 'https://keystone.api.sjc3.rackspacecloud.com/v3' --auth-version 3 --os-application-credential-id '{{ image_upload_secret.application_credential_id }}' --os-application-credential-secret '{{ image_upload_secret.application_credential_secret }}' --os-auth-type v3applicationcredential upload images-a3d39eaeea5f '{{ ansible_user_dir }}/dib-images/{{ build_diskimage_image_name }}.{{ upload_image_format }}' --object-name '{{ zuul.build }}-{{ build_diskimage_image_name }}.{{ upload_image_format }}' --verbose --use-slo --segment-size 500M

View File

@ -6,6 +6,8 @@
state: present
name:
- python3-yaml
# The following are required for the image upload
- python3-swiftclient
- name: Setup dib directories
become: true
shell: |

View File

@ -1,10 +0,0 @@
- hosts: all
tasks:
- name: Create directory
file:
path: /home/zuul/dib-images
state: directory
- name: Create fake test image
copy:
content: "test image"
dest: /home/zuul/dib-images/debian-bullseye.qcow2

View File

@ -1,83 +0,0 @@
# Copyright 2014 Rackspace Australia
# Copyright 2018 Red Hat, Inc
# Copyright 2024 Acme Gating, 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.
import os
import traceback
import openstack
import requests.exceptions
import keystoneauth1.exceptions
from ansible.module_utils.basic import AnsibleModule
def get_cloud(cloud):
if isinstance(cloud, dict):
config = openstack.config.loader.OpenStackConfig().get_one(**cloud)
return openstack.connection.Connection(config=config)
else:
return openstack.connect(cloud=cloud)
def run(cloud, container, filename, delete_after=None):
name = os.path.split(filename)[-1]
data = open(filename, 'rb')
headers = {}
if delete_after:
headers['x-delete-after'] = str(delete_after)
endpoint = cloud.object_store.get_endpoint()
cloud.create_object(container,
name=name,
data=data,
**headers)
url = os.path.join(endpoint, container, name)
return url
def ansible_main():
module = AnsibleModule(
argument_spec=dict(
cloud=dict(required=True, type='raw'),
container=dict(required=True, type='str'),
filename=dict(required=True, type='path'),
delete_after=dict(type='int'),
)
)
p = module.params
cloud = get_cloud(p.get('cloud'))
try:
url = run(
cloud, p.get('container'), p.get('filename'),
delete_after=p.get('delete_after'),
)
except (keystoneauth1.exceptions.http.HttpError,
requests.exceptions.RequestException):
s = "Error uploading to %s.%s" % (cloud.name, cloud.config.region_name)
s += "\n" + traceback.format_exc()
module.fail_json(
changed=False,
msg=s,
cloud=cloud.name,
region_name=cloud.config.region_name)
module.exit_json(
changed=True,
url=url,
)
if __name__ == '__main__':
ansible_main()

View File

@ -1,33 +0,0 @@
- name: Get sha256 hash
stat:
path: "{{ filename }}"
checksum_algorithm: sha256
register: sha256
- name: Get md5 hash
stat:
path: "{{ filename }}"
checksum_algorithm: md5
register: md5
- name: Upload image to swift
no_log: true
image_upload_swift:
cloud: "{{ cloud }}"
container: "{{ container }}"
filename: "{{ filename }}"
register: upload_results
- name: Return artifact to Zuul
zuul_return:
data:
zuul:
artifacts:
- name: '{{ upload_image_format }} image'
url: '{{ upload_results.url }}'
metadata:
type: 'zuul_image'
image_name: '{{ build_diskimage_image_name }}'
format: '{{ upload_image_format }}'
sha256: '{{ sha256.stat.checksum }}'
md5sum: '{{ md5.stat.checksum }}'

View File

@ -2,8 +2,15 @@
name: opendev-build-diskimage-base
description: |
The abstract base job for building VM images used in OpenDev's Zuul
If the variable ``image_upload_secret`` is provided (as a
secret) this job will upload the resulting image (this should be
done in image build pipelines). Otherwise, it will only build
the image without uploading it (this can be useful for check
pipelines).
parent: build-diskimage
timeout: 7200
post-timeout: 7200
abstract: true
pre-run:
- playbooks/opendev-build-diskimage-base/pre.yaml

View File

@ -1,13 +1,11 @@
- project:
check:
jobs:
- noop
- opendev-build-diskimage-debian-bullseye
gate:
jobs:
- opendev-build-diskimage-debian-bullseye:
# Temporarily skip the actual image build
run: playbooks/test.yaml
voting: false
secrets:
name: image_upload_secret
secret: image-upload-secret
- name: image_upload_secret
secret: image-upload-secret
pass-to-parent: true

View File

@ -23,4 +23,3 @@
WY6G7EbQ2VFNvPs4xUf9AOwaRwNl6bYbhjCoH50S2G0n24Vt1Y8oogSoxHeaULHLuBlnZ
JI5eUvwZwa6ByeLJ6YMxN8nUuW+8jWCjlN7x4rGDpZMkNvlO1Mtx8/gpetBYv7EbdeJN3
Dyv2odY9ME+LN0TGLJBpCPZM2wO77PlGwyJ6Xk2fHLOW4AV7ubzW7wJ8qRMzyY=