6 changed files with 365 additions and 58 deletions
@ -0,0 +1,5 @@ |
|||
# README |
|||
|
|||
This is a modified version of the start_compose module from the repo https://github.com/redhat-cop/infra.osbuild, commit 6e3416233c84623b2edd503a4b50d15c61d6c155. |
|||
|
|||
The module has been patched to specify the ostree ref when starting a compose of type "ostree-commit". |
|||
@ -0,0 +1,339 @@ |
|||
#!/usr/bin/python |
|||
# Copyright: Red Hat Inc. |
|||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) |
|||
|
|||
ANSIBLE_METADATA = { |
|||
"metadata_version": "1.1", |
|||
"status": ["preview"], |
|||
"supported_by": "community", |
|||
} |
|||
|
|||
DOCUMENTATION = """ |
|||
--- |
|||
module: start_compose2 |
|||
short_description: Start an ostree compose |
|||
description: |
|||
- Start an ostree compose |
|||
author: |
|||
- Adam Miller (@maxamillion) |
|||
- Chris Santiago (@resoluteCoder) |
|||
options: |
|||
blueprint: |
|||
description: |
|||
- Name of blueprint to iniate a build for |
|||
type: str |
|||
required: true |
|||
size: |
|||
description: |
|||
- Image size expressed in MiB |
|||
type: int |
|||
default: 0 |
|||
required: false |
|||
profile: |
|||
description: |
|||
- Path to profile toml file |
|||
type: str |
|||
default: "" |
|||
required: false |
|||
image_name: |
|||
description: |
|||
- Image name |
|||
type: str |
|||
default: "" |
|||
required: false |
|||
allow_duplicate: |
|||
description: |
|||
- Allow a duplicate version'd compose. |
|||
- (Default osbuild composer functionality is to allow duplicate composes) |
|||
type: bool |
|||
default: True |
|||
required: false |
|||
compose_type: |
|||
description: |
|||
- type of compose |
|||
type: str |
|||
default: "edge-commit" |
|||
required: false |
|||
choices: |
|||
- ami |
|||
- edge-commit |
|||
- edge-container |
|||
- edge-installer |
|||
- edge-raw-image |
|||
- edge-simplified-installer |
|||
- image-installer |
|||
- oci |
|||
- openstack |
|||
- qcow2 |
|||
- tar |
|||
- vhd |
|||
- vmdk |
|||
- iot-commit |
|||
- iot-container |
|||
- iot-installer |
|||
- iot-raw-image |
|||
- container |
|||
ostree_ref: |
|||
description: |
|||
- ostree ref |
|||
type: str |
|||
default: "" |
|||
required: false |
|||
ostree_parent: |
|||
description: |
|||
- ostree parent |
|||
type: str |
|||
default: "" |
|||
required: false |
|||
ostree_url: |
|||
description: |
|||
- ostree URL |
|||
type: str |
|||
default: "" |
|||
required: false |
|||
timeout: |
|||
description: |
|||
- timeout for osbuild-compose requests, in seconds |
|||
type: int |
|||
default: 120 |
|||
required: false |
|||
notes: |
|||
- THIS MODULE IS NOT IDEMPOTENT UNLESS C(allow_duplicate) is set to C(false) |
|||
- The params C(profile) and C(image_name) are required together. |
|||
- The C(profile) option is not fully implemented at this time. |
|||
""" |
|||
|
|||
EXAMPLES = """ |
|||
- name: Start ostree compose size 4096 |
|||
start_compose2: |
|||
blueprint: rhel-for-edge-demo |
|||
image_name: testimage |
|||
size: 4096 |
|||
|
|||
- name: Start ostree compose with idempotent transaction |
|||
start_compose2: |
|||
blueprint: rhel-for-edge-demo |
|||
allow_duplicate: false |
|||
""" |
|||
import json # noqa E402 |
|||
import socket |
|||
from typing import Any # noqa E402 |
|||
|
|||
from ansible.module_utils.basic import AnsibleModule # noqa E402 |
|||
from ansible_collections.infra.osbuild.plugins.module_utils.weldr import Weldr # noqa E402 |
|||
|
|||
argument_spec = dict( |
|||
blueprint=dict(type="str", required=True), |
|||
size=dict(type="int", required=False, default=0), |
|||
profile=dict(type="str", required=False, default=""), |
|||
image_name=dict(type="str", required=False, default=""), |
|||
allow_duplicate=dict(type="bool", required=False, default=True), |
|||
compose_type=dict( |
|||
type="str", |
|||
required=False, |
|||
default="edge-commit", |
|||
choices=[ |
|||
"ami", |
|||
"edge-commit", |
|||
"edge-container", |
|||
"edge-installer", |
|||
"edge-raw-image", |
|||
"edge-simplified-installer", |
|||
"image-installer", |
|||
"oci", |
|||
"openstack", |
|||
"qcow2", |
|||
"tar", |
|||
"vhd", |
|||
"vmdk", |
|||
"iot-commit", |
|||
"iot-container", |
|||
"iot-installer", |
|||
"iot-raw-image", |
|||
"container", |
|||
], |
|||
), |
|||
ostree_ref=dict(type="str", required=False, default=""), |
|||
ostree_parent=dict(type="str", required=False, default=""), |
|||
ostree_url=dict(type="str", required=False, default=""), |
|||
timeout=dict(type="int", required=False, default=120), |
|||
) |
|||
|
|||
|
|||
def start_compose(module, weldr): |
|||
changed: bool = False |
|||
dupe_compose: list = [] |
|||
blueprint_info: dict = weldr.api.get_blueprints_info(module.params["blueprint"]) |
|||
blueprint_version: int = blueprint_info["blueprints"][0]["version"] |
|||
|
|||
# Add check if compose_type is supported |
|||
supported_compose_type: dict = weldr.api.get_compose_types() |
|||
|
|||
is_supported: dict = next((item for item in supported_compose_type["types"] if item["name"] == module.params["compose_type"]), {}) |
|||
|
|||
if not is_supported: |
|||
module.fail_json( |
|||
msg="%s is not a valid image type, valid types are: %s" |
|||
% (module.params["compose_type"], [[v for k, v in t.items() if k == "name"] for t in supported_compose_type["types"]]), |
|||
changed=changed |
|||
) |
|||
else: |
|||
if not is_supported["enabled"]: |
|||
module.fail_json( |
|||
msg="%s is not a supported image type, supported image types are: %s" |
|||
% (module.params["compose_type"], [[v for k, v in t.items() if k == "enabled" and v is True] for t in supported_compose_type["types"]]), |
|||
changed=changed |
|||
) |
|||
|
|||
if not module.params["allow_duplicate"]: |
|||
# only do all this query and filtering if needed |
|||
|
|||
compose_queue: dict = weldr.api.get_compose_queue() |
|||
# {"new":[],"run":[{"id":"930a1584-8737-4b61-ba77-582780f0ff2d","blueprint":"base-image-with-tmux","version":"0.0.5","compose_type":"edge-commit","image_size":0,"queue_status":"RUNNING","job_created":1654620015.4107578,"job_started":1654620015.415151}]} |
|||
|
|||
compose_queue_run_dupe: list = [ |
|||
compose for compose in compose_queue["run"] if (compose["blueprint"] == module.params["blueprint"]) and (compose["version"] == blueprint_version) |
|||
] |
|||
compose_queue_new_dupe: list = [ |
|||
compose for compose in compose_queue["new"] if (compose["blueprint"] == module.params["blueprint"]) and (compose["version"] == blueprint_version) |
|||
] |
|||
|
|||
compose_finished: dict = weldr.api.get_compose_finished() |
|||
# {"finished":[{"id":"930a1584-8737-4b61-ba77-582780f0ff2d","blueprint":"base-image-with-tmux","version":"0.0.5","compose_type":"edge-commit","image_size":8192,"queue_status":"FINISHED","job_created":1654620015.4107578,"job_started":1654620015.415151,"job_finished":1654620302.9069786}]} |
|||
compose_finished_dupe: list = [ |
|||
compose |
|||
for compose in compose_finished["finished"] |
|||
if (compose["blueprint"] == module.params["blueprint"]) and (compose["version"] == blueprint_version) |
|||
] |
|||
|
|||
compose_failed: dict = weldr.api.get_compose_failed() |
|||
# {"failed":[]} |
|||
compose_failed_dupe: list = [ |
|||
compose |
|||
for compose in compose_failed["failed"] |
|||
if (compose["blueprint"] == module.params["blueprint"]) and (compose["version"] == blueprint_version) |
|||
] |
|||
|
|||
dupe_compose: list = compose_queue_run_dupe + compose_queue_new_dupe + compose_failed_dupe + compose_finished_dupe |
|||
|
|||
if module.params["allow_duplicate"] or (len(dupe_compose) == 0): |
|||
# FIXME - build to POST payload and POST that ish |
|||
compose_settings: dict[str, Any] = { |
|||
"blueprint_name": module.params["blueprint"], |
|||
"compose_type": module.params["compose_type"], |
|||
"branch": "master", |
|||
"size": module.params["size"], |
|||
} |
|||
|
|||
if "edge-commit" in module.params["compose_type"] or "installer" in module.params["compose_type"] or "raw" in module.params["compose_type"]: |
|||
compose_settings["ostree"] = { |
|||
"ref": module.params["ostree_ref"], |
|||
"parent": module.params["ostree_parent"], |
|||
"url": module.params["ostree_url"], |
|||
} |
|||
|
|||
try: |
|||
result: dict = weldr.api.post_compose(json.dumps(compose_settings), timeout=module.params["timeout"]) |
|||
except socket.timeout: |
|||
# it's possible we don't get a response back from weldr because on the |
|||
# very first run including a new content source composer will build a repo cache |
|||
# and when that happens we get an empty JSON response |
|||
|
|||
compose_queue: dict = weldr.api.get_compose_queue() |
|||
# {"new":[],"run":[{"id":"930a1584-8737-4b61-ba77-582780f0ff2d","blueprint":"base-image-with-tmux","version":"0.0.5","compose_type":"edge-commit","image_size":0,"queue_status":"RUNNING","job_created":1654620015.4107578,"job_started":1654620015.415151}]} |
|||
|
|||
submitted_compose_uuid: str = "" |
|||
|
|||
submitted_compose_found_run: list[dict[str, str]] = [ |
|||
compose |
|||
for compose in compose_queue["run"] |
|||
if (compose["blueprint"] == module.params["blueprint"]) and (compose["version"] == blueprint_version) |
|||
] |
|||
if submitted_compose_found_run: |
|||
# we expect it to be RUNNING, so check that first |
|||
submitted_compose_uuid: str = submitted_compose_found_run[0]["id"] |
|||
else: |
|||
# didn't find it running, check for NEW queue status |
|||
submitted_compose_found_new: list = [ |
|||
compose |
|||
for compose in compose_queue["new"] |
|||
if (compose["blueprint"] == module.params["blueprint"]) and (compose["version"] == blueprint_version) |
|||
] |
|||
|
|||
if submitted_compose_found_new: |
|||
submitted_compose_uuid: str = submitted_compose_found_new[0]["id"] |
|||
|
|||
else: |
|||
# it's not RUNNING and not NEW, so check for FAILURE state |
|||
compose_failed: dict = weldr.api.get_compose_failed() |
|||
# {"failed":[]} |
|||
submitted_compose_found_failed: list = [ |
|||
compose |
|||
for compose in compose_failed["failed"] |
|||
if (compose["blueprint"] == module.params["blueprint"]) and (compose["version"] == blueprint_version) |
|||
] |
|||
if submitted_compose_found_failed: |
|||
submitted_compose_uuid: str = submitted_compose_found_failed[0]["id"] |
|||
else: |
|||
module.fail_json( |
|||
msg="Unable to determine state of build, check osbuild-composer system logs. Also, consider increasing the request timeout", |
|||
changed=changed |
|||
) |
|||
|
|||
if submitted_compose_uuid: |
|||
result: dict = weldr.api.get_compose_status(submitted_compose_uuid) |
|||
result['body'] = { |
|||
'build_id': submitted_compose_uuid |
|||
} |
|||
|
|||
if "status_code" in result.keys(): |
|||
if result["status_code"] >= 400: |
|||
module.fail_json( |
|||
msg="Compose returned body: {0}, msg {1}, and status_code {2}".format(result["body"], result["error_msg"], result["status_code"]), |
|||
changed=changed |
|||
) |
|||
|
|||
# Having received a non-400+ response, we know a compose has started |
|||
changed: bool = True |
|||
|
|||
compose_output_types: dict[str, list[str]] = { |
|||
"tar": ["tar", "edge-commit", "iot-commit", "edge-container", "iot-container", "container"], |
|||
"iso": ["edge-installer", "edge-simplified-installer", "iot-installer", "image-installer"], |
|||
"qcow2": ["qcow2", "openstack", "oci"], |
|||
"vmdk": ["vmdk"], |
|||
"vhd": ["vhd"], |
|||
"raw.xz": ["edge-raw-image", "iot-raw-image"], |
|||
"ami": ["ami"], |
|||
} |
|||
|
|||
output_type: str = "" |
|||
for compose_type, compose_type_list in compose_output_types.items(): |
|||
if module.params["compose_type"] in compose_type_list: |
|||
output_type: str = compose_type |
|||
result["output_type"] = output_type |
|||
|
|||
module.exit_json(msg="Compose submitted to queue", result=result, changed=changed) |
|||
|
|||
else: |
|||
changed: bool = False |
|||
module.exit_json( |
|||
msg="Not queuing a duplicate versioned compose without allow_duplicate set to true", |
|||
changed=changed, |
|||
) |
|||
|
|||
|
|||
def main() -> None: |
|||
module: AnsibleModule = AnsibleModule( |
|||
argument_spec=argument_spec, |
|||
required_together=[["image_name", "profile"]], |
|||
required_if=[ |
|||
["compose_type", "edge-installer", ["ostree_url"]], |
|||
["compose_type", "iot-installer", ["ostree_url"]], |
|||
], |
|||
) |
|||
weldr: Weldr = Weldr(module) |
|||
start_compose(module, weldr) |
|||
|
|||
|
|||
if __name__ == "__main__": |
|||
main() |
|||
Loading…
Reference in new issue