Skip to content

Commit

Permalink
Support specifying upload options for image builds
Browse files Browse the repository at this point in the history
The upload options are expected to be provided as a JSON file. The same
options will be used for all image type and architecture combinations,
similarly as it is done for ostree options.

Extend unit tests to cover the newly added functionality.
  • Loading branch information
thozza authored and ondrejbudai committed Aug 31, 2022
1 parent 4e32ae5 commit c76e97d
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 0 deletions.
9 changes: 9 additions & 0 deletions plugins/builder/osbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def __init__(self, arch: str, image_type: str, repos: List):
self.image_type = image_type
self.repositories = repos
self.ostree: Optional[OSTreeOptions] = None
self.upload_options: Optional[Dict] = None

def as_dict(self):
arch = self.architecture
Expand All @@ -128,6 +129,8 @@ def as_dict(self):
}
if self.ostree:
res["ostree"] = self.ostree.as_dict(self.architecture)
if self.upload_options:
res["upload_options"] = self.upload_options

return res

Expand Down Expand Up @@ -688,6 +691,12 @@ def handler(self, name, version, distro, image_type, target, arches, opts):
for ireq in ireqs:
ireq.ostree = ostree

# Cloud upload options
upload_options = opts.get("upload_options")
if upload_options:
for ireq in ireqs:
ireq.upload_options = upload_options

self.logger.debug("Creating compose: %s (%s)\n koji: %s\n images: %s",
nvr, distro, self.koji_url,
str([i.as_dict() for i in ireqs]))
Expand Down
7 changes: 7 additions & 0 deletions plugins/cli/osbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def parse_args(argv):

parser.add_option("--customizations", type=str, default=None, dest="customizations",
help="Additional customizations to pass to Composer (json file)")
parser.add_option("--upload-options", type=str, default=None, dest="upload_options",
help="Cloud target upload options (json file)")
parser.add_option("--nowait", action="store_false", dest="wait",
help="Don't wait on image creation")
parser.add_option("--ostree-parent", type=str, dest="ostree_parent",
Expand Down Expand Up @@ -140,6 +142,11 @@ def handle_osbuild_image(options, session, argv):
with open(args.customizations, "r", encoding="utf-8") as f:
opts["customizations"] = json.load(f)

# cloud upload options handling
if args.upload_options:
with open(args.upload_options, "r", encoding="utf-8") as f:
opts["upload_options"] = json.load(f)

# Do some early checks to be able to give quick feedback
check_target(session, target)

Expand Down
94 changes: 94 additions & 0 deletions plugins/hub/osbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@
"type": "object",
"$ref": "#/definitions/ostree"
},
"upload_options": {
"oneOf": [
{"$ref": "#/definitions/AWSEC2UploadOptions"},
{"$ref": "#/definitions/AWSS3UploadOptions"},
{"$ref": "#/definitions/GCPUploadOptions"},
{"$ref": "#/definitions/AzureUploadOptions"},
{"$ref": "#/definitions/ContainerUploadOptions"}
],
},
"repo": {
"type": "array",
"description": "Repositories",
Expand All @@ -113,6 +122,91 @@
"description": "Omit tagging the result"
}
}
},
"AWSEC2UploadOptions": {
"type": "object",
"additionalProperties": False,
"required": ["region", "share_with_accounts"],
"properties": {
"region": {
"type": "string",
},
"snapshot_name": {
"type": "string",
},
"share_with_accounts": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"AWSS3UploadOptions": {
"type": "object",
"additionalProperties": False,
"required": ["region"],
"properties": {
"region": {
"type": "string"
}
}
},
"AzureUploadOptions": {
"type": "object",
"additionalProperties": False,
"required": ["tenant_id", "subscription_id", "resource_group", "location"],
"properties": {
"tenant_id": {
"type": "string"
},
"subscription_id": {
"type": "string"
},
"resource_group": {
"type": "string"
},
"location": {
"type": "string"
},
"image_name": {
"type": "string",
}
}
},
"GCPUploadOptions": {
"type": "object",
"additionalProperties": False,
"required": ["region", "bucket"],
"properties": {
"region": {
"type": "string"
},
"bucket": {
"type": "string"
},
"image_name": {
"type": "string",
},
"share_with_accounts": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"ContainerUploadOptions": {
"type": "object",
"additionalProperties": False,
"properties": {
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
}
}
}
Expand Down
41 changes: 41 additions & 0 deletions test/unit/test_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,9 @@ def test_compose_repo_complex(self):

for ir in ireqs:
arch = ir["architecture"]
# Piggyback on this test case to test that no upload_options
# are set, if they were not provided in the args.
self.assertIsNone(ir.get("upload_options"))
repos = ir["repositories"]
assert len(repos) == 3

Expand All @@ -1209,6 +1212,44 @@ def test_compose_repo_complex(self):
ps = r.get("package_sets")
assert ps and ps == ["a", "b", "c", "d"]

@httpretty.activate
def test_compose_upload_options_global(self):
# Check we properly handle compose requests with global upload options
session = self.mock_session()
handler = self.make_handler(session=session)

arches = ["x86_64", "aarch64"]
upload_options = {
"region": "us-east-1",
"share_with_accounts": ["123456789"]
}
args = ["name", "version", "distro",
"image_type",
"fedora-candidate",
arches,
{"upload_options": upload_options}]

url = self.plugin.DEFAULT_COMPOSER_URL
composer = MockComposer(url, architectures=arches)
composer.httpretty_register()

res = handler.handler(*args)
assert res, "invalid compose result"
compose_id = res["composer"]["id"]
compose = composer.composes.get(compose_id)
self.assertIsNotNone(compose)

ireqs = compose["request"]["image_requests"]

# Check we got all the requested architectures
ireq_arches = [i["architecture"] for i in ireqs]
diff = set(arches) ^ set(ireq_arches)
self.assertEqual(diff, set())

for ir in ireqs:
uo = ir["upload_options"]
self.assertEqual(uo, upload_options)

@httpretty.activate
def test_compose_status_retry(self):
compose_id = "43e57e63-ab32-4a8d-854d-3bbc117fdce3"
Expand Down

0 comments on commit c76e97d

Please sign in to comment.