Skip to content

Commit

Permalink
[Scaleway] Add module to manage container registries (#5399)
Browse files Browse the repository at this point in the history
* [Scaleway] Add module to manage container registries

Signed-off-by: Lunik <[email protected]>

* first review

Signed-off-by: Lunik <[email protected]>

* lint documentation on return value

Signed-off-by: Lunik <[email protected]>

* second review

Signed-off-by: Lunik <[email protected]>

* second review *bis

Signed-off-by: Lunik <[email protected]>

* second review *ter

Signed-off-by: Lunik <[email protected]>

* Fix typo.

Signed-off-by: Lunik <[email protected]>
Co-authored-by: Felix Fontein <[email protected]>
  • Loading branch information
Lunik and felixfontein authored Oct 23, 2022
1 parent 91cac4c commit 2680739
Show file tree
Hide file tree
Showing 13 changed files with 805 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .github/BOTMETA.yml
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ files:
maintainers: $team_scaleway
$modules/cloud/scaleway/scaleway_compute_private_network.py:
maintainers: pastral
$modules/cloud/scaleway/scaleway_container_registry.py:
maintainers: Lunik
$modules/cloud/scaleway/scaleway_container_registry_info.py:
maintainers: Lunik
$modules/cloud/scaleway/scaleway_database_backup.py:
maintainers: guillaume_ro_fr
$modules/cloud/scaleway/scaleway_image_info.py:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -509,3 +509,6 @@ $RECYCLE.BIN/
*.lnk

# End of https://www.toptal.com/developers/gitignore/api/vim,git,macos,linux,pydev,emacs,dotenv,python,windows,webstorm,pycharm+all,jupyternotebooks

# Integration tests cloud configs
tests/integration/cloud-config-*.ini
4 changes: 4 additions & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,10 @@ plugin_routing:
redirect: community.general.cloud.scaleway.scaleway_compute
scaleway_compute_private_network:
redirect: community.general.cloud.scaleway.scaleway_compute_private_network
scaleway_container_registry:
redirect: community.general.cloud.scaleway.scaleway_container_registry
scaleway_container_registry_info:
redirect: community.general.cloud.scaleway.scaleway_container_registry_info
scaleway_database_backup:
redirect: community.general.cloud.scaleway.scaleway_database_backup
scaleway_image_facts:
Expand Down
33 changes: 33 additions & 0 deletions plugins/doc_fragments/scaleway_waitable_resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-

# Copyright (c) 2022, Guillaume MARTINEZ <[email protected]>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type


class ModuleDocFragment(object):

# Standard documentation fragment
DOCUMENTATION = r'''
options:
wait:
description:
- Wait for the resource to reach its desired state before returning.
type: bool
default: true
wait_timeout:
type: int
description:
- Time to wait for the resource to reach the expected state.
required: false
default: 300
wait_sleep_time:
type: int
description:
- Time to wait before every attempt to check the state of the resource.
required: false
default: 3
'''
101 changes: 101 additions & 0 deletions plugins/module_utils/scaleway.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import json
import re
import sys
import datetime
import time

from ansible.module_utils.basic import env_fallback
from ansible.module_utils.urls import fetch_url
Expand All @@ -26,6 +28,14 @@ def scaleway_argument_spec():
)


def scaleway_waitable_resource_argument_spec():
return dict(
wait=dict(type="bool", default=True),
wait_timeout=dict(type="int", default=300),
wait_sleep_time=dict(type="int", default=3),
)


def payload_from_object(scw_object):
return dict(
(k, v)
Expand Down Expand Up @@ -63,6 +73,25 @@ def parse_pagination_link(header):
return parsed_relations


def filter_sensitive_attributes(container, attributes):
for attr in attributes:
container[attr] = "SENSITIVE_VALUE"

return container


def resource_attributes_should_be_changed(target, wished, verifiable_mutable_attributes, mutable_attributes):
diff = dict()
for attr in verifiable_mutable_attributes:
if wished[attr] is not None and target[attr] != wished[attr]:
diff[attr] = wished[attr]

if diff:
return dict((attr, wished[attr]) for attr in mutable_attributes)
else:
return diff


class Response(object):

def __init__(self, resp, info):
Expand Down Expand Up @@ -169,6 +198,78 @@ def update(self, path, data=None, headers=None, params=None):
def warn(self, x):
self.module.warn(str(x))

def fetch_state(self, resource):
self.module.debug("fetch_state of resource: %s" % resource["id"])
response = self.get(path=self.api_path + "/%s" % resource["id"])

if response.status_code == 404:
return "absent"

if not response.ok:
msg = 'Error during state fetching: (%s) %s' % (response.status_code, response.json)
self.module.fail_json(msg=msg)

try:
self.module.debug("Resource %s in state: %s" % (resource["id"], response.json["status"]))
return response.json["status"]
except KeyError:
self.module.fail_json(msg="Could not fetch state in %s" % response.json)

def fetch_paginated_resources(self, resource_key, **pagination_kwargs):
response = self.get(
path=self.api_path,
params=pagination_kwargs)

status_code = response.status_code
if not response.ok:
self.module.fail_json(msg='Error getting {0} [{1}: {2}]'.format(
resource_key,
response.status_code, response.json['message']))

return response.json[resource_key]

def fetch_all_resources(self, resource_key, **pagination_kwargs):
resources = []

result = [None]
while len(result) != 0:
result = self.fetch_paginated_resources(resource_key, **pagination_kwargs)
resources += result
if 'page' in pagination_kwargs:
pagination_kwargs['page'] += 1
else:
pagination_kwargs['page'] = 2

return resources

def wait_to_complete_state_transition(self, resource, stable_states, force_wait=False):
wait = self.module.params["wait"]

if not (wait or force_wait):
return

wait_timeout = self.module.params["wait_timeout"]
wait_sleep_time = self.module.params["wait_sleep_time"]

# Prevent requesting the ressource status too soon
time.sleep(wait_sleep_time)

start = datetime.datetime.utcnow()
end = start + datetime.timedelta(seconds=wait_timeout)

while datetime.datetime.utcnow() < end:
self.module.debug("We are going to wait for the resource to finish its transition")

state = self.fetch_state(resource)
if state in stable_states:
self.module.debug("It seems that the resource is not in transition anymore.")
self.module.debug("load-balancer in state: %s" % self.fetch_state(resource))
break

time.sleep(wait_sleep_time)
else:
self.module.fail_json(msg="Server takes too long to finish its transition")


SCALEWAY_LOCATION = {
'par1': {
Expand Down
Loading

0 comments on commit 2680739

Please sign in to comment.