diff options
Diffstat (limited to 'collections-debian-merged/ansible_collections/hetzner/hcloud')
172 files changed, 17244 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/.gitignore b/collections-debian-merged/ansible_collections/hetzner/hcloud/.gitignore new file mode 100644 index 00000000..c6fc14ad --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/.gitignore @@ -0,0 +1,387 @@ + +# Created by https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv +# Edit at https://www.gitignore.io/?templates=git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv + +### dotenv ### +.env + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +#!! ERROR: jupyternotebook is undefined. Use list command to see defined gitignore types !!# + +### Linux ### + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### PyCharm+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### pydev ### +.pydevproject + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# Mr Developer +.mr.developer.cfg +.project + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### WebStorm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff + +# Generated files + +# Sensitive or high-churn files + +# Gradle + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake + +# Mongo Explorer plugin + +# File-based project format + +# IntelliJ + +# mpeltonen/sbt-idea plugin + +# JIRA plugin + +# Cursive Clojure plugin + +# Crashlytics plugin (for Android Studio and IntelliJ) + +# Editor-based Rest Client + +# Android studio 3.1+ serialized cache file + +### WebStorm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/**/sonarlint/ + +# SonarQube Plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator/ + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/.gitlab-ci.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/.gitlab-ci.yml new file mode 100644 index 00000000..57b1b4d1 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/.gitlab-ci.yml @@ -0,0 +1,164 @@ +stages: + - sanity + - integration + +ansible-devel-1/4: + stage: sanity + image: python:3.6-buster + allow_failure: true + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh devel/sanity/1 + tags: + - hc-bladerunner + +ansible-devel-2/4: + stage: sanity + image: python:3.6-buster + allow_failure: true + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh devel/sanity/2 + tags: + - hc-bladerunner + +ansible-devel-3/4: + stage: sanity + image: python:3.6-buster + allow_failure: true + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh devel/sanity/3 + tags: + - hc-bladerunner + +ansible-devel-4/4: + stage: sanity + image: python:3.6-buster + allow_failure: true + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh devel/sanity/4 + tags: + - hc-bladerunner + +ansible-210-1/4: + stage: sanity + image: python:3.6-buster + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh 2.10/sanity/1 + tags: + - hc-bladerunner + +ansible-210-2/4: + stage: sanity + image: python:3.6-buster + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh 2.10/sanity/2 + tags: + - hc-bladerunner + +ansible-210-3/4: + stage: sanity + image: python:3.6-buster + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh 2.10/sanity/3 + tags: + - hc-bladerunner + +ansible-210-4/4: + stage: sanity + image: python:3.6-buster + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh 2.10/sanity/4 + tags: + - hc-bladerunner + +ansible-29-1/4: + stage: sanity + image: python:3.6-buster + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh 2.9/sanity/1 + tags: + - hc-bladerunner + +ansible-29-2/4: + stage: sanity + image: python:3.6-buster + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh 2.9/sanity/2 + tags: + - hc-bladerunner + +ansible-29-3/4: + stage: sanity + image: python:3.6-buster + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh 2.9/sanity/3 + tags: + - hc-bladerunner + +ansible-29-4/4: + stage: sanity + image: python:3.6-buster + except: + - tags + script: + - bash tests/utils/gitlab/gitlab.sh 2.9/sanity/4 + tags: + - hc-bladerunner + +ansible-devel-1/3: + stage: integration + image: python:3.6-buster + except: + - tags + script: + - echo "$HCLOUD_TOKEN" >> "$(pwd)/hcloud_token.txt" + - echo "py38-$CI_JOB_ID" >> "$(pwd)/prefix.txt" + - bash tests/utils/gitlab/gitlab.sh devel/hcloud/3.6/1 + tags: + - hc-bladerunner + + +ansible-devel-2/3: + stage: integration + image: python:3.6-buster + except: + - tags + script: + - echo "$HCLOUD_TOKEN" >> "$(pwd)/hcloud_token.txt" + - echo "py39-$CI_JOB_ID" >> "$(pwd)/prefix.txt" + - bash tests/utils/gitlab/gitlab.sh devel/hcloud/3.6/2 + tags: + - hc-bladerunner + +ansible-devel-3/3: + stage: integration + image: python:3.6-buster + except: + - tags + script: + - echo "$HCLOUD_TOKEN" >> "$(pwd)/hcloud_token.txt" + - echo "py39-$CI_JOB_ID" >> "$(pwd)/prefix.txt" + - bash tests/utils/gitlab/gitlab.sh devel/hcloud/3.6/3 + tags: + - hc-bladerunner diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/CHANGELOG.rst b/collections-debian-merged/ansible_collections/hetzner/hcloud/CHANGELOG.rst new file mode 100644 index 00000000..2832f9a7 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/CHANGELOG.rst @@ -0,0 +1,76 @@ +============================================== +Hetzner Cloud Ansible Collection Release Notes +============================================== + +.. contents:: Topics + +v1.2.1 +====== + +Bugfixes +-------- +- Inventory Restore Python 2.7 compatibility + + +v1.2.0 +====== + +Minor Changes +------------- + +- Dynamic Inventory Add option to specifiy the token_env variable which is used for identification if now token is set +- Improve imports of API Exception +- hcloud_server_network Allow updating alias ips +- hcloud_subnetwork Allow creating vswitch subnetworks + +New Modules +----------- + +- hcloud_load_balancer_info - Gather infos about your Hetzner Cloud load_balancers. + +v1.1.0 +====== + +Minor Changes +------------- + +- hcloud_floating_ip Allow creating Floating IP with protection +- hcloud_load_balancer Allow creating Load Balancer with protection +- hcloud_network Allow creating Network with protection +- hcloud_server Allow creating server with protection +- hcloud_volume Allow creating Volumes with protection + +Bugfixes +-------- + +- hcloud_floating_ip Fix idempotency when floating ip is assigned to server + +v1.0.0 +====== + +Minor Changes +------------- + +- hcloud_load_balancer Allow changing the type of a Load Balancer +- hcloud_server Allow the creation of servers with enabled backups + +v0.2.0 +====== + +Bugfixes +-------- + +- hcloud inventory plugin - Allow usage of hcloud.yml and hcloud.yaml - this was removed by error within the migration from build-in ansible to our collection + +v0.1.0 +====== + +New Modules +----------- + +- hcloud_floating_ip - Create and manage cloud Floating IPs on the Hetzner Cloud. +- hcloud_load_balancer - Create and manage cloud Load Balancers on the Hetzner Cloud. +- hcloud_load_balancer_network - Manage the relationship between Hetzner Cloud Networks and Load Balancers +- hcloud_load_balancer_service - Create and manage the services of cloud Load Balancers on the Hetzner Cloud. +- hcloud_load_balancer_target - Manage Hetzner Cloud Load Balancer targets +- hcloud_load_balancer_type_info - Gather infos about the Hetzner Cloud Load Balancer types. diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/COPYING b/collections-debian-merged/ansible_collections/hetzner/hcloud/COPYING new file mode 100644 index 00000000..10926e87 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. + diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/FILES.json b/collections-debian-merged/ansible_collections/hetzner/hcloud/FILES.json new file mode 100644 index 00000000..eda0aaec --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/FILES.json @@ -0,0 +1,2056 @@ +{ + "files": [ + { + "name": ".", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "meta/runtime.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b4b578c3b0063c1ef211c696ec9158f75f39a395a3e9be13425c2a78c3740cb9", + "format": 1 + }, + { + "name": "changelogs", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "changelogs/config.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cfa06a718f8b3c226c944d5f33fd3ba5a07415293b07146631503539bea5d1ea", + "format": 1 + }, + { + "name": "changelogs/changelog.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "87cacedd54f163c2ba13d76e527bdda1c883084025d01e76751f89219b6dbcfe", + "format": 1 + }, + { + "name": "changelogs/.gitignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "919ef00776e7d2ff349950ac4b806132aa9faf006e214d5285de54533e443b33", + "format": 1 + }, + { + "name": "COPYING", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0ae0485a5bd37a63e63603596417e4eb0e653334fa6c7f932ca3a0e85d4af227", + "format": 1 + }, + { + "name": "plugins", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/module_utils", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/module_utils/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "plugins/module_utils/hcloud.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6b1903cfe01b2da9c786dac3f272a079802d830f7351c3cb89e11f292ff4b7f1", + "format": 1 + }, + { + "name": "plugins/inventory", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/inventory/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "plugins/inventory/hcloud.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c73b9e487d8e2eba10e375a41ffd455087ad5e2f5d9116d36206bd6c2e7913d7", + "format": 1 + }, + { + "name": "plugins/doc_fragments", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/doc_fragments/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "plugins/doc_fragments/hcloud.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "224f4646d2d213ca52c5f0ed8ae665651e55e3a9d90f4dddfe5447d90b2abcd3", + "format": 1 + }, + { + "name": "plugins/modules", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/modules/hcloud_network.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8203a2ae529d02c5bd585a8a8494b9ffba4495abbb50629375d096bad30cfd53", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_server_facts.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "446068bc883596000e4504e6c144a74ca904effcbfda4d0ca6aa44940844aaf8", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_floating_ip_facts.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "66ab0912eee104e2cb71dd37ec769b8bcd7fbdf99da8eef4e5273921ccd49cbe", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_load_balancer_network.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "05ecadef86a5bdd740ef717b36619d146fd81f0cafe58aeb5379d06f285b7d2a", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_server_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "446068bc883596000e4504e6c144a74ca904effcbfda4d0ca6aa44940844aaf8", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_load_balancer.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b8abc3a38f7eb6f7e74af3a29554f5b339c5aba029949b5246ca3ff9252a4e8b", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_datacenter_facts.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "73d46cc61148b85cd0316154fdb81b18a42b467325e5744bacbfbbb6af514f8c", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_server_network.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4ebcbf05345e63fdfa1282fd96d80134b350bdc68d119a68a24f668efdb31404", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_ssh_key_facts.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "892aed8ae0b7c6f774eaa100c0da0783d6131b97baba5d81699cf2af570d35bd", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_certificate_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "855f63917f75af5569f57cc33a6a360bccfc02243c9dc59fdf38bb2be31b34c3", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_datacenter_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "73d46cc61148b85cd0316154fdb81b18a42b467325e5744bacbfbbb6af514f8c", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_location_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "69fa37a55cbbd1d7ce21abdf86403442c240c5ea128947d7b44412d053d3016d", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_load_balancer_type_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8b0908510d39df65055a3f9239c5b93b71c3d4a359fd3c6ae8c64646628bf6c1", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_location_facts.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "69fa37a55cbbd1d7ce21abdf86403442c240c5ea128947d7b44412d053d3016d", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_load_balancer_service.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "215bebedbb86dfc9089c7ca12e148e75f471e404d846e404ca75b67d53b1846f", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_image_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ad749e72e6e5325cf26f4804812551c60a3ed406e75caf11c7f4fd2d4d2007f4", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_network_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "772dff9ce369127c6d8c766c8aae104532308411f89f82045e017fbaee4fe84f", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_load_balancer_target.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2653cd9784b7cf4ff4b0aec7612fff37b2e405af802c3139c7f3236ed3012b61", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_volume.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fd76ce59902015efc40a43574d487ab66b51c47d18d6f62ec72eb0c457b254df", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_rdns.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "61acd1b4634a2d1f4e3622a9369cceae01e6f8e9bc63ff510737415179f9548a", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_server_type_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7b9183f5d1e07b903d59d2af9b7c695478adc1797dd61d59de9f4cb8eb5db1ca", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_floating_ip.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "92ebe5645394caad0f56f3574afe2a6b4693ce1c9ba2bfd9c146d554a6fae157", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_ssh_key_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "892aed8ae0b7c6f774eaa100c0da0783d6131b97baba5d81699cf2af570d35bd", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_server_type_facts.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7b9183f5d1e07b903d59d2af9b7c695478adc1797dd61d59de9f4cb8eb5db1ca", + "format": 1 + }, + { + "name": "plugins/modules/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_image_facts.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ad749e72e6e5325cf26f4804812551c60a3ed406e75caf11c7f4fd2d4d2007f4", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_certificate.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "275fd6277c3615513ed4d22d7854f93a57e3225e135a659c6454137d191dd2da", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_route.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "44a5f0aa244751d0a51c63cfd4474c9b16be73d76fafa43a8acfaf5b1f11df64", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_server.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fe5ecbc8e86a28649316ea893d59b645c8ee913563b10ba7608c7469dc3e072f", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_ssh_key.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0cccf6ecad3cac14ede5a58ca985ac174c67c64498e5a52c9366cea4337c6a17", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_volume_facts.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1be0874dc7da8b266ec02577dd9109fb8071dc6d40852dae78c8bf09ece8c1b0", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_floating_ip_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "66ab0912eee104e2cb71dd37ec769b8bcd7fbdf99da8eef4e5273921ccd49cbe", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_load_balancer_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5c48d5ec5081a5381a035cf7b9a6272b81f75f9102e42b7c8c21d3207802221f", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_subnetwork.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ee43ae805d0067d9b226ead1bfb8ce740fbda7569a31bc1391f18d8b2f8995af", + "format": 1 + }, + { + "name": "plugins/modules/hcloud_volume_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1be0874dc7da8b266ec02577dd9109fb8071dc6d40852dae78c8bf09ece8c1b0", + "format": 1 + }, + { + "name": "CHANGELOG.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5829f1b6c7063c39303ff2bf1527192113a5d484692c9c19900de2696a23a886", + "format": 1 + }, + { + "name": ".gitlab-ci.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1f6a78e5006d04406e2d889ec840d85250feff00cbc2a23fa09cc1798e8e194a", + "format": 1 + }, + { + "name": "tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/requirements.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "bdf5cf6c8dad0da0a4e726e341c0ba44124759ce387da8c1ab158a6662cb2bb6", + "format": 1 + }, + { + "name": "tests/sanity", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/sanity/requirements.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c8a4ac4bfdef88e75d6e748e35a42fb4915947dfa2b7dd788626fd829600e014", + "format": 1 + }, + { + "name": "tests/integration", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "df576bb718f55147bb2cebabd4d9597350018d8822ae06acef853e3377d9dacf", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6046d0d6217a122060d5475f76a7cf78577850caca478faa95e8483cbb53d753", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c35ec449e5b6556c7c7205e598fdc98b7dff12a9b4a6be290b3fffd936422dc4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cd53b64efc25ba17d0b8dd5db034e63ddd2bc30bd912766fd8e6f4bed585510a", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_network", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_network/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_network/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_network/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_network/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3e6a9c2bf10ea4a9deac6d22874c15244e4ac4615b59d2ef130feee4e3a7af61", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_network/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_network/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1c40ed3cdce067725ce85e113cd17f6462840570bd584662538784e8830ba6d2", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ee118e09355fa5085716b09c60ededee02cb6c104d15c293fb472bf1462ce821", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b41df455c2d9c29dad9308de40a386808471e6c386ca104bb9f3fcd0f7b86555", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_subnetwork", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_subnetwork/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_subnetwork/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_subnetwork/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a48fdbe183742154c38aa6c1658c907b2fac5a90170aca3f813c65234a33845e", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_subnetwork/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_subnetwork/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5cb1793ca396033d9ad4fe54838da01861653b7898f91b1476a7fb5f88fc6991", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_subnetwork/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_subnetwork/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a1b71650fde2c710274a8e017cca68e43832ed6360f5aa83eb5909f8f8dc00fd", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1d6fc1e922be2f83fe92a2cce093a713b95fc4e609aa4c374d9308ff1ec3d08d", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c595101d0d1838a92198660b95c472514fc903757989378c3905cb1d644e5fcd", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6e57d8acecc565433bacbbf7047387474700f9f57200f1a03d5d12948c49386f", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_floating_ip/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8fa4c135f29ccbe6563a77d7c2eb5eac7909459a53d7a69bc516fbc42f8dabd5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "67633416742aa9e9480b796190982c057f5a9b7cff7c57625029c3958b07bfb4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f657286f00631c9b264009a06a4fd667a47de6f108d10e6bcd454fad518ca97d", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_network/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "93baf9ebc898fb93f961dad90033a1a50e0aa9aa4c9cc197aa78587738e42616", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_route", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_route/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_route/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cf9085335e8c310c57255c35c9a7f9ed61437277b0eb23af810565ed3a1b63d9", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_route/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_route/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_route/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c8325d94bc19646c1e3f9bd9d2cd049103a0375d37003f5eea801417987d1e06", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_route/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_route/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "754a7fee0573b3a5c27cba4c53e7f66bb36ca485e153305efbd3b332d52c36d7", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f977a248bf7c50a9f2765b1553da531ce03bc453f0af2b20a860dfdcf700d3c2", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2adfa5d38588f02b5540d12b07623b11cad61d7e3b30eca187c9df2cce855b93", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2267e95d9e1412bfa94ca2ecb76ecf5ea027753e4b50f87cf59c9450f9090b00", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7f92f7b3339191886638aa24095180b60af477e10314e059bb1e3671c571d509", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f2ac15fb16f8e251a10741c938b839bbe4786accfa7ac34a52624f1b03c4d1a9", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2267e95d9e1412bfa94ca2ecb76ecf5ea027753e4b50f87cf59c9450f9090b00", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c11de83da62fb58106ae5cc42b59fc55edfff557682656d9c0d4530d8d9c505a", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_ssh_key/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ee90ee27c8375ce531832b39ee4a3ae2f420343ac2efe2c4444a6ae8c5917a52", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_location_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_location_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_location_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_location_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_location_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_location_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "49468959c5285a8c2c8bccefa9c1d9dca5f0239158eb292bb8f4b768af0fc387", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_location_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_location_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6915c116ecff24f780c1e1268142e89399335eed0b756c9179f00cefd5dc6956", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1b20be52b226752cbaf5fa1a0c189361ccecd53ea0863b7e0b8b07c5016adabc", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_volume_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "85ad9de1a55e08bfa43a2fc065a515eda84b9c4cc411fee92084c7f47ad7485b", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4c8ffb7b82917fe7ca28a48bacc9b9a6ceae89e8fa1867711a4d6272605803d7", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "37823961c8a8ad27ade27df4d929423373e9ad5d8037240f6f137747e39f3c72", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_datacenter_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_datacenter_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_datacenter_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_datacenter_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_datacenter_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_datacenter_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "40e03f6534c2f7203b2b3f2aaa720b36d1ef10bfb6e6ab7f46e34bed8c976ec0", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_datacenter_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_datacenter_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fb76e4cbdc32b97d3a94f29edde5b730544c0006f157a89787069990044b4db5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_type_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_type_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_type_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_type_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_type_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_type_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1be0206ddc23c1059392c89a7d0e321ceccf2f3f04a0a33f2d72ff209fb51b62", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_type_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_type_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cbc4ccf4a22f6d7cf98a9c1c5710a93611f4992817dd6ffd8260e7c503274852", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_service", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_service/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_service/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_service/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_service/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_service/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e2fc1ea9b6c91b5e7979f9900ab1cd81efe8aaf0e657cc7fa0b3b5076af7c055", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_service/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_service/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "863d2c7c325991e0c83139253285f482976c7f90b5cf21422b8b390f2d564fc6", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_sshkey", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_sshkey/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_sshkey/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "016d4c789eb18f7d6cd03c5cd32300a5e1ccec5bb6695aa35b60105c0a5d5d2d", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a613e3027e9e2dd78cda228949082fa43284dae03c297b946e974ee3c0e76129", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7ed7d7d7857c25a2ae886c496afb411cc3d4918871ffa7261ef6de4eee39c909", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "096e178a932e3ee2385d05cbffd661e637be2578d65a9d9d7a99cf53739cf7aa", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f977a248bf7c50a9f2765b1553da531ce03bc453f0af2b20a860dfdcf700d3c2", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "701c31b2b52635600eb1556c68c4924f2a8a22b5da4323a445d8cb31412acb1d", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6e5494d36b85275f2dd65d9e871553d4b97bb194f3c7102bf8eea017e4756036", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "54abe03862bd73dde2caed2d60073ae9a9f43aa16642f877891afde936dbadd1", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_certificate_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3e9247cbc9aa06b1c689414aa36c75e6dfb29e64018ea49411875a01c574aab4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_type_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_type_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_type_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_type_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_type_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e5641db8ac5de1ea6954d78949fbf6ac9829f86f9135ae9361859aa8220d1892", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_type_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "56fc91b4ed15be279423b2859d700b70589bb1e10bee32a829fa263253917fa2", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_network", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_network/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_network/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_network/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "864269fd363e663625df637c1cca2ad3a47ca364bbbad59da58cb75c6002a827", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_network/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_network/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b014b86e13e0e10f3b7cd1d94965ef4f8c624136662a0f534e34a38739aecbf6", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_network/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_server_network/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4aaf9b7f5c70031287488817d492fb19e9b23cb8e2f886bcf9c7f2b6bb647bf0", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_selfsigned_certificate", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_selfsigned_certificate/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e4d4d2cd1069f55d65c9e6c8017b934023575ecb0540445ac65714d85d422323", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_rdns", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_rdns/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_rdns/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cf9085335e8c310c57255c35c9a7f9ed61437277b0eb23af810565ed3a1b63d9", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_rdns/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_rdns/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_rdns/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "67d2e240c3add68c8276b477e63c725757f3dcee116e8dd0cddd34d09223026c", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_rdns/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_rdns/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a6d34200e348025b85276ed0fd20d2d1ef289f893cedd0a269aef95567d2a2ca", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_image_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_image_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_image_info/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_image_info/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b02a426443d5b1f10b9edc49bad4cdaf57c66f422bdaf60f1b4b904529431fb5", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_image_info/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_image_info/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e68277c0b4e480098115380f2b03968ffea0f3318de6f9d640e768be0d479545", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_image_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_image_info/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2969d23cfa6870f0df9924fd64064ad2aa335181b05e0399329478bce669ac62", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_target", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_target/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_target/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eb96249de09a0a3fdd399aca62aa600ee7bb7b66670ffb65e000fdbe3419d986", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_target/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "899ec496fc016f5e221bdf39f63bcf73374fe136f199b14cac9dd23375c989e4", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_target/defaults", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4b3f8ebf1cfdac4bc445bbb94718fd47ffb1e9f10044c39cb8884e56d0e8a720", + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_target/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/hcloud_load_balancer_target/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "49917a272e0f3ea6d16bd63441b76c2bec09d2f08c8bf97d1495a712b13efa43", + "format": 1 + }, + { + "name": "tests/integration/requirements.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f8c3336e9a6315d376c59719374e5aced8a1be5d81934e0b39bc9483fdb49dc6", + "format": 1 + }, + { + "name": "tests/.gitignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b5726d3ec9335a09c124469eca039523847a6b0f08a083efaefd002b83326600", + "format": 1 + }, + { + "name": "tests/utils", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/utils/shippable", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/utils/shippable/check_matrix.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eca2864515b1854d55dd78b481962969ac030fa8d10a4fd4edb9833797ee85fb", + "format": 1 + }, + { + "name": "tests/utils/shippable/sanity.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a1c968fc55bac46136d755c3c9bbbc8c410bf659d41a59816f143cf313ab3cbf", + "format": 1 + }, + { + "name": "tests/utils/shippable/timing.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ebb7d3553349747ad41d80899ed353e13cf32fcbecbb6566cf36e9d2bc33703e", + "format": 1 + }, + { + "name": "tests/utils/shippable/shippable.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c76455e44c5fcb99b91304565065a7038faa8898bd09336c79d35d3b1b069d1d", + "format": 1 + }, + { + "name": "tests/utils/shippable/hcloud.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "99db6946e47cf9e49ab2fccbe0aca8ffc9aaa0918fdc9e3ef543601c55a98713", + "format": 1 + }, + { + "name": "tests/utils/shippable/timing.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f3f3cc03a997cdba719b0542fe668fc612451841cbe840ab36865f30aa54a1bd", + "format": 1 + }, + { + "name": "tests/utils/gitlab", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/utils/gitlab/gitlab.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1cee085f785834aaef060499855774c4a0035fae372bb5a9895dead5db45b92c", + "format": 1 + }, + { + "name": "tests/utils/gitlab/sanity.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fbfffdeff0e937f847ba0ab2d7f1996cb2ab0e19ce87f3ea0e2041491dacd372", + "format": 1 + }, + { + "name": "tests/utils/gitlab/integration.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b68bb45e91cd28465c3344832c467c24df2a3abf75b184ba70b0ae5a1e55e23b", + "format": 1 + }, + { + "name": "shippable.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "344f26797924cbccbe1de233cc7e917eb1b362ac8bba3fae7291a60130232809", + "format": 1 + }, + { + "name": ".gitignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "258e4be3cfda40797fe734b375b6f94c110c9a9bebce196fedce319a457ce720", + "format": 1 + }, + { + "name": "README.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c4973cd35a5ed2b70d42f55c7d22bfcaf54dec3f04229f58285102b09dd1088f", + "format": 1 + } + ], + "format": 1 +}
\ No newline at end of file diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/MANIFEST.json b/collections-debian-merged/ansible_collections/hetzner/hcloud/MANIFEST.json new file mode 100644 index 00000000..f5d10c6f --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/MANIFEST.json @@ -0,0 +1,36 @@ +{ + "collection_info": { + "namespace": "hetzner", + "name": "hcloud", + "version": "1.2.1", + "authors": [ + "Hetzner Cloud (github.com/hetznercloud)" + ], + "readme": "README.md", + "tags": [ + "hetzner", + "cloud", + "hcloud" + ], + "description": "A Collection for managing Hetzner Cloud resources", + "license": [ + "GPL-3.0-or-later" + ], + "license_file": null, + "dependencies": { + "ansible.netcommon": ">=0.0.1" + }, + "repository": "https://github.com/ansible-collections/hetzner.hcloud", + "documentation": "https://github.com/ansible-collections/hetzner.hcloud/tree/master/docs", + "homepage": "https://github.com/ansible-collections/hetzner.hcloud", + "issues": "https://github.com/ansible-collections/hetzner.hcloud/issues" + }, + "file_manifest_file": { + "name": "FILES.json", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "53cfd501f092788b834b4eafa0a921deadeb25f123a7586189f89c95fef73dda", + "format": 1 + }, + "format": 1 +}
\ No newline at end of file diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/README.md b/collections-debian-merged/ansible_collections/hetzner/hcloud/README.md new file mode 100644 index 00000000..eed66003 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/README.md @@ -0,0 +1,21 @@ +[![Run Status](https://api.shippable.com/projects/5e66776c8b17a60007e4c277/badge?branch=master)]() + +Ansible Collection: hetzner.hcloud +================================================= + +Ansible Hetzner Cloud Collection for controlling your Hetzner Cloud Resources. + +## Release notes + +See [here](https://github.com/ansible-collections/hetzner.hcloud/tree/master/CHANGELOG.rst). + + +## Publishing New Version + + +TBD Basic instructions without release branches: + +1. Create `changelogs/fragments/<version>.yml` with `release_summary:` section (which must be a string, not a list). +2. Run `antsibull-changelog release --collection-flatmap yes` +3. Make sure `CHANGELOG.rst` and `changelogs/changelog.yaml` are added to git, and the deleted fragments have been removed. +4. Tag the commit with `<version>`. Push changes and tag to the main repository. diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/.gitignore b/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/.gitignore new file mode 100644 index 00000000..6be6b533 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/.gitignore @@ -0,0 +1 @@ +/.plugin-cache.yaml diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/changelog.yaml b/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/changelog.yaml new file mode 100644 index 00000000..7e2c2f56 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/changelog.yaml @@ -0,0 +1,74 @@ +ancestor: null +releases: + 0.1.0: + modules: + - description: Create and manage cloud Floating IPs on the Hetzner Cloud. + name: hcloud_floating_ip + namespace: '' + - description: Create and manage cloud Load Balancers on the Hetzner Cloud. + name: hcloud_load_balancer + namespace: '' + - description: Manage the relationship between Hetzner Cloud Networks and Load + Balancers + name: hcloud_load_balancer_network + namespace: '' + - description: Create and manage the services of cloud Load Balancers on the Hetzner + Cloud. + name: hcloud_load_balancer_service + namespace: '' + - description: Manage Hetzner Cloud Load Balancer targets + name: hcloud_load_balancer_target + namespace: '' + - description: Gather infos about the Hetzner Cloud Load Balancer types. + name: hcloud_load_balancer_type_info + namespace: '' + release_date: '2020-06-29' + 0.2.0: + changes: + bugfixes: + - hcloud inventory plugin - Allow usage of hcloud.yml and hcloud.yaml - this + was removed by error within the migration from build-in ansible to our collection + fragments: + - inventory-allow-usage-of-pre-migration-configuration-fuiles.yml + release_date: '2020-06-30' + 1.0.0: + changes: + minor_changes: + - hcloud_load_balancer Allow changing the type of a Load Balancer + - hcloud_server Allow the creation of servers with enabled backups + fragments: + - gh7-allow-enabling-of-backups-on-server-creation.yml + - lb-allow-change-type.yml + release_date: '2020-08-11' + 1.1.0: + changes: + bugfixes: + - hcloud_floating_ip Fix idempotency when floating ip is assigned to server + minor_changes: + - hcloud_floating_ip Allow creating Floating IP with protection + - hcloud_load_balancer Allow creating Load Balancer with protection + - hcloud_network Allow creating Network with protection + - hcloud_server Allow creating server with protection + - hcloud_volume Allow creating Volumes with protection + fragments: + - fix-idempotency-floating-ip.yml + - gh-28-allow-setting-of-protection-on-creation.yml + release_date: '2020-10-05' + 1.2.0: + changes: + minor_changes: + - Dynamic Inventory Add option to specifiy the token_env variable which is used + for identification if now token is set + - Improve imports of API Exception + - hcloud_server_network Allow updating alias ips + - hcloud_subnetwork Allow creating vswitch subnetworks + modules: + - description: Gather infos about your Hetzner Cloud load_balancers. + name: hcloud_load_balancer_info + namespace: '' + release_date: '2020-12-01' + 1.2.1: + changes: + bugfixes: + - Inventory Restore Python 2.7 compatibility + release_date: '2020-12-16' diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/config.yaml b/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/config.yaml new file mode 100644 index 00000000..739603a4 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/changelogs/config.yaml @@ -0,0 +1,28 @@ +title: Hetzner Cloud Ansible Collection +changelog_filename_template: ../CHANGELOG.rst +changelog_filename_version_depth: 0 +changes_file: changelog.yaml +changes_format: combined +keep_fragments: false +mention_ancestor: true +new_plugins_after_name: removed_features +notesdir: fragments +prelude_section_name: release_summary +prelude_section_title: Release Summary +sections: +- - major_changes + - Major Changes +- - minor_changes + - Minor Changes +- - breaking_changes + - Breaking Changes / Porting Guide +- - deprecated_features + - Deprecated Features +- - removed_features + - Removed Features (previously deprecated) +- - security_fixes + - Security Fixes +- - bugfixes + - Bugfixes +- - known_issues + - Known Issues diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/meta/runtime.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/meta/runtime.yml new file mode 100644 index 00000000..1f7fb2f4 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/meta/runtime.yml @@ -0,0 +1,35 @@ +requires_ansible: '>=2.9.10' +plugin_routing: + modules: + hcloud_location_facts: + deprecation: + removal_version: 2.0.0 + warning_text: see plugin documentation for details + hcloud_server_type_facts: + deprecation: + removal_version: 2.0.0 + warning_text: see plugin documentation for details + hcloud_image_facts: + deprecation: + removal_version: 2.0.0 + warning_text: see plugin documentation for details + hcloud_volume_facts: + deprecation: + removal_version: 2.0.0 + warning_text: see plugin documentation for details + hcloud_floating_ip_facts: + deprecation: + removal_version: 2.0.0 + warning_text: see plugin documentation for details + hcloud_ssh_key_facts: + deprecation: + removal_version: 2.0.0 + warning_text: see plugin documentation for details + hcloud_datacenter_facts: + deprecation: + removal_version: 2.0.0 + warning_text: see plugin documentation for details + hcloud_server_facts: + deprecation: + removal_version: 2.0.0 + warning_text: see plugin documentation for details diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/doc_fragments/__init__.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/doc_fragments/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/doc_fragments/__init__.py diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/doc_fragments/hcloud.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/doc_fragments/hcloud.py new file mode 100644 index 00000000..2548b1e6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/doc_fragments/hcloud.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +class ModuleDocFragment(object): + DOCUMENTATION = ''' +options: + api_token: + description: + - This is the API Token for the Hetzner Cloud. + required: True + type: str + endpoint: + description: + - This is the API Endpoint for the Hetzner Cloud. + default: https://api.hetzner.cloud/v1 + type: str +requirements: + - hcloud-python >= 1.0.0 +seealso: +- name: Documentation for Hetzner Cloud API + description: Complete reference for the Hetzner Cloud API. + link: https://docs.hetzner.cloud/ +''' diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/inventory/__init__.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/inventory/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/inventory/__init__.py diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.py new file mode 100644 index 00000000..080327e7 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.py @@ -0,0 +1,269 @@ +# Copyright (c) 2019 Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +DOCUMENTATION = r''' + name: hcloud + plugin_type: inventory + author: + - Lukas Kaemmerling (@lkaemmerling) + short_description: Ansible dynamic inventory plugin for the Hetzner Cloud. + requirements: + - python >= 2.7 + - hcloud-python >= 1.0.0 + description: + - Reads inventories from the Hetzner Cloud API. + - Uses a YAML configuration file that ends with hcloud.(yml|yaml). + extends_documentation_fragment: + - constructed + options: + plugin: + description: marks this as an instance of the "hcloud" plugin + required: true + choices: ["hcloud"] + token: + description: The Hetzner Cloud API Token. + required: false + token_env: + description: Environment variable to load the Hetzner Cloud API Token from. + default: HCLOUD_TOKEN + type: str + required: false + connect_with: + description: Connect to the server using the value from this field. + default: public_ipv4 + type: str + choices: + - public_ipv4 + - hostname + - ipv4_dns_ptr + - private_ipv4 + locations: + description: Populate inventory with instances in this location. + default: [] + type: list + required: false + types: + description: Populate inventory with instances with this type. + default: [] + type: list + required: false + images: + description: Populate inventory with instances with this image name, only available for system images. + default: [] + type: list + required: false + label_selector: + description: Populate inventory with instances with this label. + default: "" + type: str + required: false + network: + description: Populate inventory with instances which are attached to this network name or ID. + default: "" + type: str + required: false +''' + +EXAMPLES = r""" +# Minimal example. `HCLOUD_TOKEN` is exposed in environment. +plugin: hcloud + +# Example with locations, types, groups and token +plugin: hcloud +token: foobar +locations: + - nbg1 +types: + - cx11 + +# Group by a location with prefix e.g. "hcloud_location_nbg1" +# and image_os_flavor without prefix and separator e.g. "ubuntu" +# and status with prefix e.g. "server_status_running" +plugin: hcloud +keyed_groups: + - key: location + prefix: hcloud_location + - key: image_os_flavor + separator: "" + - key: status + prefix: server_status +""" + +import os +from ansible.errors import AnsibleError +from ansible.module_utils._text import to_native +from ansible.plugins.inventory import BaseInventoryPlugin, Constructable +from ansible.release import __version__ + +try: + from hcloud import hcloud + from hcloud import APIException +except ImportError: + raise AnsibleError("The Hetzner Cloud dynamic inventory plugin requires hcloud-python.") + + +class InventoryModule(BaseInventoryPlugin, Constructable): + NAME = 'hetzner.hcloud.hcloud' + + def _configure_hcloud_client(self): + self.token_env = self.get_option("token_env") + self.api_token = self.get_option("token") or os.getenv(self.token_env) + if self.api_token is None: + raise AnsibleError( + "Please specify a token, via the option token, via environment variable HCLOUD_TOKEN " + "or via custom environment variable set by token_env option." + ) + + self.endpoint = os.getenv("HCLOUD_ENDPOINT") or "https://api.hetzner.cloud/v1" + + self.client = hcloud.Client(token=self.api_token, + api_endpoint=self.endpoint, + application_name="ansible-inventory", + application_version=__version__) + + def _test_hcloud_token(self): + try: + # We test the API Token against the location API, because this is the API with the smallest result + # and not controllable from the customer. + self.client.locations.get_all() + except APIException: + raise AnsibleError("Invalid Hetzner Cloud API Token.") + + def _get_servers(self): + if len(self.get_option("label_selector")) > 0: + self.servers = self.client.servers.get_all(label_selector=self.get_option("label_selector")) + else: + self.servers = self.client.servers.get_all() + + def _filter_servers(self): + if self.get_option("network"): + try: + self.network = self.client.networks.get_by_name(self.get_option("network")) + if self.network is None: + self.network = self.client.networks.get_by_id(self.get_option("network")) + except APIException: + raise AnsibleError( + "The given network is not found.") + + tmp = [] + for server in self.servers: + for server_private_network in server.private_net: + if server_private_network.network.id == self.network.id: + tmp.append(server) + self.servers = tmp + + if self.get_option("locations"): + tmp = [] + for server in self.servers: + if server.datacenter.location.name in self.get_option("locations"): + tmp.append(server) + self.servers = tmp + + if self.get_option("types"): + tmp = [] + for server in self.servers: + if server.server_type.name in self.get_option("types"): + tmp.append(server) + self.servers = tmp + + if self.get_option("images"): + tmp = [] + for server in self.servers: + if server.image is not None and server.image.os_flavor in self.get_option("images"): + tmp.append(server) + self.servers = tmp + + def _set_server_attributes(self, server): + self.inventory.set_variable(server.name, "id", to_native(server.id)) + self.inventory.set_variable(server.name, "name", to_native(server.name)) + self.inventory.set_variable(server.name, "status", to_native(server.status)) + self.inventory.set_variable(server.name, "type", to_native(server.server_type.name)) + + # Network + self.inventory.set_variable(server.name, "ipv4", to_native(server.public_net.ipv4.ip)) + self.inventory.set_variable(server.name, "ipv6_network", to_native(server.public_net.ipv6.network)) + self.inventory.set_variable(server.name, "ipv6_network_mask", to_native(server.public_net.ipv6.network_mask)) + + if self.get_option("network"): + for server_private_network in server.private_net: + if server_private_network.network.id == self.network.id: + self.inventory.set_variable(server.name, "private_ipv4", to_native(server_private_network.ip)) + + if self.get_option("connect_with") == "public_ipv4": + self.inventory.set_variable(server.name, "ansible_host", to_native(server.public_net.ipv4.ip)) + elif self.get_option("connect_with") == "hostname": + self.inventory.set_variable(server.name, "ansible_host", to_native(server.name)) + elif self.get_option("connect_with") == "ipv4_dns_ptr": + self.inventory.set_variable(server.name, "ansible_host", to_native(server.public_net.ipv4.dns_ptr)) + elif self.get_option("connect_with") == "private_ipv4": + if self.get_option("network"): + for server_private_network in server.private_net: + if server_private_network.network.id == self.network.id: + self.inventory.set_variable(server.name, "ansible_host", to_native(server_private_network.ip)) + else: + raise AnsibleError( + "You can only connect via private IPv4 if you specify a network") + + # Server Type + if server.image is not None and server.image.name is not None: + self.inventory.set_variable(server.name, "server_type", to_native(server.image.name)) + else: + self.inventory.set_variable(server.name, "server_type", to_native("No Image name found.")) + + # Datacenter + self.inventory.set_variable(server.name, "datacenter", to_native(server.datacenter.name)) + self.inventory.set_variable(server.name, "location", to_native(server.datacenter.location.name)) + + # Image + if server.image is not None: + self.inventory.set_variable(server.name, "image_id", to_native(server.image.id)) + self.inventory.set_variable(server.name, "image_os_flavor", to_native(server.image.os_flavor)) + if server.image.name is not None: + self.inventory.set_variable(server.name, "image_name", to_native(server.image.name)) + else: + self.inventory.set_variable(server.name, "image_name", to_native(server.image.description)) + else: + self.inventory.set_variable(server.name, "image_id", to_native("No Image ID found")) + self.inventory.set_variable(server.name, "image_name", to_native("No Image Name found")) + self.inventory.set_variable(server.name, "image_os_flavor", to_native("No Image OS Flavor found")) + + # Labels + self.inventory.set_variable(server.name, "labels", dict(server.labels)) + + def verify_file(self, path): + """Return the possibly of a file being consumable by this plugin.""" + return ( + super(InventoryModule, self).verify_file(path) and + path.endswith(("hcloud.yaml", "hcloud.yml")) + ) + + def parse(self, inventory, loader, path, cache=True): + super(InventoryModule, self).parse(inventory, loader, path, cache) + self._read_config_data(path) + self._configure_hcloud_client() + self._test_hcloud_token() + self._get_servers() + self._filter_servers() + + # Add a top group 'hcloud' + self.inventory.add_group(group="hcloud") + + for server in self.servers: + self.inventory.add_host(server.name, group="hcloud") + self._set_server_attributes(server) + + # Use constructed if applicable + strict = self.get_option('strict') + + # Composed variables + self._set_composite_vars(self.get_option('compose'), self.inventory.get_host(server.name).get_vars(), server.name, strict=strict) + + # Complex groups based on jinja2 conditionals, hosts that meet the conditional are added to group + self._add_host_to_composed_groups(self.get_option('groups'), {}, server.name, strict=strict) + + # Create groups based on variable values and add the corresponding hosts to it + self._add_host_to_keyed_groups(self.get_option('keyed_groups'), {}, server.name, strict=strict) diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/module_utils/__init__.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/module_utils/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/module_utils/__init__.py diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/module_utils/hcloud.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/module_utils/hcloud.py new file mode 100644 index 00000000..e1bc6c58 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/module_utils/hcloud.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> + +# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +from ansible.module_utils.ansible_release import __version__ +from ansible.module_utils.basic import env_fallback, missing_required_lib + +try: + import hcloud + from hcloud import APIException + + HAS_HCLOUD = True +except ImportError: + HAS_HCLOUD = False + + +class Hcloud(object): + def __init__(self, module, represent): + self.module = module + self.represent = represent + self.result = {"changed": False, self.represent: None} + if not HAS_HCLOUD: + module.fail_json(msg=missing_required_lib("hcloud-python")) + self._build_client() + + def _build_client(self): + self.client = hcloud.Client( + token=self.module.params["api_token"], + api_endpoint=self.module.params["endpoint"], + application_name="ansible-module", + application_version=__version__, + ) + + def _mark_as_changed(self): + self.result["changed"] = True + + @staticmethod + def base_module_arguments(): + return { + "api_token": { + "type": "str", + "required": True, + "fallback": (env_fallback, ["HCLOUD_TOKEN"]), + "no_log": True, + }, + "endpoint": {"type": "str", "default": "https://api.hetzner.cloud/v1"}, + } + + def _prepare_result(self): + """Prepare the result for every module + + :return: dict + """ + return {} + + def get_result(self): + if getattr(self, self.represent) is not None: + self.result[self.represent] = self._prepare_result() + return self.result diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/__init__.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/__init__.py diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate.py new file mode 100644 index 00000000..9b6c6864 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate.py @@ -0,0 +1,258 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_certificate + +short_description: Create and manage certificates on the Hetzner Cloud. + + +description: + - Create, update and manage certificates on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@lkaemmerling) + +options: + id: + description: + - The ID of the Hetzner Cloud certificate to manage. + - Only required if no certificate I(name) is given + type: int + name: + description: + - The Name of the Hetzner Cloud certificate to manage. + - Only required if no certificate I(id) is given or a certificate does not exists. + type: str + labels: + description: + - User-defined labels (key-value pairs) + type: dict + certificate: + description: + - Certificate and chain in PEM format, in order so that each record directly certifies the one preceding. + - Required if certificate does not exists. + type: str + private_key: + description: + - Certificate key in PEM format. + - Required if certificate does not exists. + type: str + state: + description: + - State of the certificate. + default: present + choices: [ absent, present ] + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic certificate + hcloud_certificate: + name: my-certificate + certificate: "ssh-rsa AAAjjk76kgf...Xt" + private_key: "ssh-rsa AAAjjk76kgf...Xt" + state: present + +- name: Create a certificate with labels + hcloud_certificate: + name: my-certificate + certificate: "ssh-rsa AAAjjk76kgf...Xt" + private_key: "ssh-rsa AAAjjk76kgf...Xt" + labels: + key: value + mylabel: 123 + state: present + +- name: Ensure the certificate is absent (remove if needed) + hcloud_certificate: + name: my-certificate + state: absent +""" + +RETURN = """ +hcloud_certificate: + description: The certificate instance + returned: Always + type: complex + contains: + id: + description: Numeric identifier of the certificate + returned: always + type: int + sample: 1937415 + name: + description: Name of the certificate + returned: always + type: str + sample: my website cert + fingerprint: + description: Fingerprint of the certificate + returned: always + type: str + sample: "03:c7:55:9b:2a:d1:04:17:09:f6:d0:7f:18:34:63:d4:3e:5f" + certificate: + description: Certificate and chain in PEM format + returned: always + type: str + sample: "-----BEGIN CERTIFICATE-----..." + domain_names: + description: List of Domains and Subdomains covered by the Certificate + returned: always + type: dict + not_valid_before: + description: Point in time when the Certificate becomes valid (in ISO-8601 format) + returned: always + type: str + not_valid_after: + description: Point in time when the Certificate stops being valid (in ISO-8601 format) + returned: always + type: str + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud.certificates.domain import Certificate + from hcloud.certificates.domain import Server + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudCertificate(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_certificate") + self.hcloud_certificate = None + + def _prepare_result(self): + return { + "id": to_native(self.hcloud_certificate.id), + "name": to_native(self.hcloud_certificate.name), + "fingerprint": to_native(self.hcloud_certificate.fingerprint), + "certificate": to_native(self.hcloud_certificate.certificate), + "not_valid_before": to_native(self.hcloud_certificate.not_valid_before), + "not_valid_after": to_native(self.hcloud_certificate.not_valid_after), + "domain_names": [to_native(domain) for domain in self.hcloud_certificate.domain_names], + "labels": self.hcloud_certificate.labels + } + + def _get_certificate(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_certificate = self.client.certificates.get_by_id( + self.module.params.get("id") + ) + elif self.module.params.get("name") is not None: + self.hcloud_certificate = self.client.certificates.get_by_name( + self.module.params.get("name") + ) + + except APIException as e: + self.module.fail_json(msg=e.message) + + def _create_certificate(self): + self.module.fail_on_missing_params( + required_params=["name", "certificate", "private_key"] + ) + params = { + "name": self.module.params.get("name"), + "certificate": self.module.params.get("certificate"), + "private_key": self.module.params.get("private_key"), + "labels": self.module.params.get("labels") + } + + if not self.module.check_mode: + try: + self.client.certificates.create(**params) + except APIException as e: + self.module.fail_json(msg=e.message) + self._mark_as_changed() + self._get_certificate() + + def _update_certificate(self): + name = self.module.params.get("name") + if name is not None and self.hcloud_certificate.name != name: + self.module.fail_on_missing_params( + required_params=["id"] + ) + if not self.module.check_mode: + self.hcloud_certificate.update(name=name) + self._mark_as_changed() + + labels = self.module.params.get("labels") + if labels is not None and self.hcloud_certificate.labels != labels: + if not self.module.check_mode: + self.hcloud_certificate.update(labels=labels) + self._mark_as_changed() + + self._get_certificate() + + def present_certificate(self): + self._get_certificate() + if self.hcloud_certificate is None: + self._create_certificate() + else: + self._update_certificate() + + def delete_certificate(self): + self._get_certificate() + if self.hcloud_certificate is not None: + if not self.module.check_mode: + self.client.certificates.delete(self.hcloud_certificate) + self._mark_as_changed() + self.hcloud_certificate = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + certificate={"type": "str"}, + private_key={"type": "str"}, + labels={"type": "dict"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + required_one_of=[['id', 'name']], + required_if=[['state', 'present', ['name']]], + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudCertificate.define_module() + + hcloud = AnsibleHcloudCertificate(module) + state = module.params.get("state") + if state == "absent": + hcloud.delete_certificate() + elif state == "present": + hcloud.present_certificate() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate_info.py new file mode 100644 index 00000000..479613af --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_certificate_info.py @@ -0,0 +1,167 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_certificate_info +short_description: Gather infos about your Hetzner Cloud certificates. +description: + - Gather facts about your Hetzner Cloud certificates. +author: + - Lukas Kaemmerling (@LKaemmerling) +options: + id: + description: + - The ID of the certificate you want to get. + type: int + name: + description: + - The name of the certificate you want to get. + type: str + label_selector: + description: + - The label selector for the certificate you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud certificate infos + hcloud_certificate_info: + register: output +- name: Print the gathered infos + debug: + var: output.hcloud_certificate_info +""" + +RETURN = """ +hcloud_certificate_info: + description: The certificate instances + returned: Always + type: complex + contains: + id: + description: Numeric identifier of the certificate + returned: always + type: int + sample: 1937415 + name: + description: Name of the certificate + returned: always + type: str + sample: my website cert + fingerprint: + description: Fingerprint of the certificate + returned: always + type: str + sample: "03:c7:55:9b:2a:d1:04:17:09:f6:d0:7f:18:34:63:d4:3e:5f" + certificate: + description: Certificate and chain in PEM format + returned: always + type: str + sample: "-----BEGIN CERTIFICATE-----..." + domain_names: + description: List of Domains and Subdomains covered by the Certificate + returned: always + type: dict + not_valid_before: + description: Point in time when the Certificate becomes valid (in ISO-8601 format) + returned: always + type: str + not_valid_after: + description: Point in time when the Certificate stops being valid (in ISO-8601 format) + returned: always + type: str + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudCertificateInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_certificate_info") + self.hcloud_certificate_info = None + + def _prepare_result(self): + certificates = [] + + for certificate in self.hcloud_certificate_info: + if certificate: + certificates.append({ + "id": to_native(certificate.id), + "name": to_native(certificate.name), + "fingerprint": to_native(certificate.fingerprint), + "certificate": to_native(certificate.certificate), + "not_valid_before": to_native(certificate.not_valid_before), + "not_valid_after": to_native(certificate.not_valid_after), + "domain_names": [to_native(domain) for domain in certificate.domain_names], + "labels": certificate.labels + }) + return certificates + + def get_certificates(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_certificate_info = [self.client.certificates.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_certificate_info = [self.client.certificates.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_certificate_info = self.client.certificates.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_certificate_info = self.client.certificates.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudCertificateInfo.define_module() + + hcloud = AnsibleHcloudCertificateInfo(module) + hcloud.get_certificates() + result = hcloud.get_result() + + ansible_info = { + 'hcloud_certificate_info': result['hcloud_certificate_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_facts.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_facts.py new file mode 100644 index 00000000..6c53672a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_facts.py @@ -0,0 +1,165 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_datacenter_info + +short_description: Gather info about the Hetzner Cloud datacenters. + +description: + - Gather info about your Hetzner Cloud datacenters. + - This module was called C(hcloud_datacenter_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_datacenter_facts). + Note that the M(hetzner.hcloud.hcloud_datacenter_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_datacenter_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the datacenter you want to get. + type: int + name: + description: + - The name of the datacenter you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud datacenter info + hcloud_datacenter_info: + register: output +- name: Print the gathered info + debug: + var: output +""" + +RETURN = """ +hcloud_datacenter_info: + description: + - The datacenter info as list + - This module was called C(hcloud_datacenter_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_datacenter_facts). + Note that the M(hetzner.hcloud.hcloud_datacenter_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_datacenter_info)! + returned: always + type: complex + contains: + id: + description: Numeric identifier of the datacenter + returned: always + type: int + sample: 1937415 + name: + description: Name of the datacenter + returned: always + type: str + sample: fsn1-dc8 + description: + description: Detail description of the datacenter + returned: always + type: str + sample: Falkenstein DC 8 + location: + description: Name of the location where the datacenter resides in + returned: always + type: str + sample: fsn1 + city: + description: City of the location + returned: always + type: str + sample: fsn1 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudDatacenterInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_datacenter_info") + self.hcloud_datacenter_info = None + + def _prepare_result(self): + tmp = [] + + for datacenter in self.hcloud_datacenter_info: + if datacenter is not None: + tmp.append({ + "id": to_native(datacenter.id), + "name": to_native(datacenter.name), + "description": to_native(datacenter.description), + "location": to_native(datacenter.location.name) + }) + + return tmp + + def get_datacenters(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_datacenter_info = [self.client.datacenters.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_datacenter_info = [self.client.datacenters.get_by_name( + self.module.params.get("name") + )] + else: + self.hcloud_datacenter_info = self.client.datacenters.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudDatacenterInfo.define_module() + + is_old_facts = module._name == 'hcloud_datacenter_facts' + if is_old_facts: + module.deprecate("The 'hcloud_datacenter_facts' module has been renamed to 'hcloud_datacenter_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + hcloud = AnsibleHcloudDatacenterInfo(module) + + hcloud.get_datacenters() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_datacenter_facts': result['hcloud_datacenter_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_datacenter_info': result['hcloud_datacenter_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_info.py new file mode 100644 index 00000000..6c53672a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_datacenter_info.py @@ -0,0 +1,165 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_datacenter_info + +short_description: Gather info about the Hetzner Cloud datacenters. + +description: + - Gather info about your Hetzner Cloud datacenters. + - This module was called C(hcloud_datacenter_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_datacenter_facts). + Note that the M(hetzner.hcloud.hcloud_datacenter_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_datacenter_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the datacenter you want to get. + type: int + name: + description: + - The name of the datacenter you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud datacenter info + hcloud_datacenter_info: + register: output +- name: Print the gathered info + debug: + var: output +""" + +RETURN = """ +hcloud_datacenter_info: + description: + - The datacenter info as list + - This module was called C(hcloud_datacenter_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_datacenter_facts). + Note that the M(hetzner.hcloud.hcloud_datacenter_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_datacenter_info)! + returned: always + type: complex + contains: + id: + description: Numeric identifier of the datacenter + returned: always + type: int + sample: 1937415 + name: + description: Name of the datacenter + returned: always + type: str + sample: fsn1-dc8 + description: + description: Detail description of the datacenter + returned: always + type: str + sample: Falkenstein DC 8 + location: + description: Name of the location where the datacenter resides in + returned: always + type: str + sample: fsn1 + city: + description: City of the location + returned: always + type: str + sample: fsn1 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudDatacenterInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_datacenter_info") + self.hcloud_datacenter_info = None + + def _prepare_result(self): + tmp = [] + + for datacenter in self.hcloud_datacenter_info: + if datacenter is not None: + tmp.append({ + "id": to_native(datacenter.id), + "name": to_native(datacenter.name), + "description": to_native(datacenter.description), + "location": to_native(datacenter.location.name) + }) + + return tmp + + def get_datacenters(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_datacenter_info = [self.client.datacenters.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_datacenter_info = [self.client.datacenters.get_by_name( + self.module.params.get("name") + )] + else: + self.hcloud_datacenter_info = self.client.datacenters.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudDatacenterInfo.define_module() + + is_old_facts = module._name == 'hcloud_datacenter_facts' + if is_old_facts: + module.deprecate("The 'hcloud_datacenter_facts' module has been renamed to 'hcloud_datacenter_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + hcloud = AnsibleHcloudDatacenterInfo(module) + + hcloud.get_datacenters() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_datacenter_facts': result['hcloud_datacenter_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_datacenter_info': result['hcloud_datacenter_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip.py new file mode 100644 index 00000000..5cba5d5d --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip.py @@ -0,0 +1,359 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_floating_ip + +short_description: Create and manage cloud Floating IPs on the Hetzner Cloud. + + +description: + - Create, update and manage cloud Floating IPs on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@lkaemmerling) +version_added: 0.1.0 +options: + id: + description: + - The ID of the Hetzner Cloud Floating IPs to manage. + - Only required if no Floating IP I(name) is given. + type: int + name: + description: + - The Name of the Hetzner Cloud Floating IPs to manage. + - Only required if no Floating IP I(id) is given or a Floating IP does not exists. + type: str + description: + description: + - The Description of the Hetzner Cloud Floating IPs. + type: str + home_location: + description: + - Home Location of the Hetzner Cloud Floating IP. + - Required if no I(server) is given and Floating IP does not exists. + type: str + server: + description: + - Server Name the Floating IP should be assigned to. + - Required if no I(home_location) is given and Floating IP does not exists. + type: str + type: + description: + - Type of the Floating IP. + - Required if Floating IP does not exists + choices: [ ipv4, ipv6 ] + type: str + force: + description: + - Force the assignment or deletion of the Floating IP. + type: bool + delete_protection: + description: + - Protect the Floating IP for deletion. + type: bool + labels: + description: + - User-defined labels (key-value pairs). + type: dict + state: + description: + - State of the Floating IP. + default: present + choices: [ absent, present ] + type: str + +requirements: + - hcloud-python >= 1.6.0 + +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic IPv4 Floating IP + hcloud_floating_ip: + name: my-floating-ip + home_location: fsn1 + type: ipv4 + state: present +- name: Create a basic IPv6 Floating IP + hcloud_floating_ip: + name: my-floating-ip + home_location: fsn1 + type: ipv6 + state: present +- name: Assign a Floating IP to a server + hcloud_floating_ip: + name: my-floating-ip + server: 1234 + state: present +- name: Assign a Floating IP to another server + hcloud_floating_ip: + name: my-floating-ip + server: 1234 + force: yes + state: present +- name: Floating IP should be absent + hcloud_floating_ip: + name: my-floating-ip + state: absent +""" + +RETURN = """ +hcloud_floating_ip: + description: The Floating IP instance + returned: Always + type: complex + contains: + id: + description: ID of the Floating IP + type: int + returned: Always + sample: 12345 + name: + description: Name of the Floating IP + type: str + returned: Always + sample: my-floating-ip + description: + description: Description of the Floating IP + type: str + returned: Always + sample: my-floating-ip + ip: + description: IP Address of the Floating IP + type: str + returned: Always + sample: 116.203.104.109 + type: + description: Type of the Floating IP + type: str + returned: Always + sample: ipv4 + home_location: + description: Name of the home location of the Floating IP + type: str + returned: Always + sample: fsn1 + server: + description: Name of the server the Floating IP is assigned to. + type: str + returned: Always + sample: "my-server" + delete_protection: + description: True if Floating IP is protected for deletion + type: bool + returned: always + sample: false + version_added: "0.1.0" + labels: + description: User-defined labels (key-value pairs) + type: dict + returned: Always + sample: + key: value + mylabel: 123 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudFloatingIP(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_floating_ip") + self.hcloud_floating_ip = None + + def _prepare_result(self): + server = None + + if self.hcloud_floating_ip.server is not None: + server = to_native(self.hcloud_floating_ip.server.name) + return { + "id": to_native(self.hcloud_floating_ip.id), + "name": to_native(self.hcloud_floating_ip.name), + "description": to_native(self.hcloud_floating_ip.description), + "ip": to_native(self.hcloud_floating_ip.ip), + "type": to_native(self.hcloud_floating_ip.type), + "home_location": to_native(self.hcloud_floating_ip.home_location.name), + "labels": self.hcloud_floating_ip.labels, + "server": server, + "delete_protection": self.hcloud_floating_ip.protection["delete"], + } + + def _get_floating_ip(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_floating_ip = self.client.floating_ips.get_by_id( + self.module.params.get("id") + ) + else: + self.hcloud_floating_ip = self.client.floating_ips.get_by_name( + self.module.params.get("name") + ) + except APIException as e: + self.module.fail_json(msg=e.message) + + def _create_floating_ip(self): + self.module.fail_on_missing_params( + required_params=["type"] + ) + + params = { + "description": self.module.params.get("description"), + "type": self.module.params.get("type"), + "name": self.module.params.get("name"), + } + if self.module.params.get("home_location") is not None: + params["home_location"] = self.client.locations.get_by_name( + self.module.params.get("home_location") + ) + elif self.module.params.get("server") is not None: + params["server"] = self.client.servers.get_by_name( + self.module.params.get("server") + ) + else: + self.module.fail_json(msg="one of the following is required: home_location, server") + + if self.module.params.get("labels") is not None: + params["labels"] = self.module.params.get("labels") + if not self.module.check_mode: + resp = self.client.floating_ips.create(**params) + self.hcloud_floating_ip = resp.floating_ip + + delete_protection = self.module.params.get("delete_protection") + if delete_protection is not None: + self.hcloud_floating_ip.change_protection(delete=delete_protection).wait_until_finished() + + self._mark_as_changed() + self._get_floating_ip() + + def _update_floating_ip(self): + try: + labels = self.module.params.get("labels") + if labels is not None and labels != self.hcloud_floating_ip.labels: + if not self.module.check_mode: + self.hcloud_floating_ip.update(labels=labels) + self._mark_as_changed() + + description = self.module.params.get("description") + if description is not None and description != self.hcloud_floating_ip.description: + if not self.module.check_mode: + self.hcloud_floating_ip.update(description=description) + self._mark_as_changed() + + server = self.module.params.get("server") + if server is not None and self.hcloud_floating_ip.server is not None: + if self.module.params.get("force") and server != self.hcloud_floating_ip.server.name: + if not self.module.check_mode: + self.hcloud_floating_ip.assign( + self.client.servers.get_by_name(server) + ) + self._mark_as_changed() + elif server != self.hcloud_floating_ip.server.name: + self.module.warn( + "Floating IP is already assigned to another server %s. You need to unassign the Floating IP or use force=yes." + % self.hcloud_floating_ip.server.name + ) + self._mark_as_changed() + elif server is not None and self.hcloud_floating_ip.server is None: + if not self.module.check_mode: + self.hcloud_floating_ip.assign( + self.client.servers.get_by_name(server) + ) + self._mark_as_changed() + elif server is None and self.hcloud_floating_ip.server is not None: + if not self.module.check_mode: + self.hcloud_floating_ip.unassign() + self._mark_as_changed() + + delete_protection = self.module.params.get("delete_protection") + if delete_protection is not None and delete_protection != self.hcloud_floating_ip.protection["delete"]: + if not self.module.check_mode: + self.hcloud_floating_ip.change_protection(delete=delete_protection).wait_until_finished() + self._mark_as_changed() + + self._get_floating_ip() + except APIException as e: + self.module.fail_json(msg=e.message) + + def present_floating_ip(self): + self._get_floating_ip() + if self.hcloud_floating_ip is None: + self._create_floating_ip() + else: + self._update_floating_ip() + + def delete_floating_ip(self): + try: + self._get_floating_ip() + if self.hcloud_floating_ip is not None: + if self.module.params.get("force") or self.hcloud_floating_ip.server is None: + if not self.module.check_mode: + self.client.floating_ips.delete(self.hcloud_floating_ip) + else: + self.module.warn( + "Floating IP is currently assigned to server %s. You need to unassign the Floating IP or use force=yes." + % self.hcloud_floating_ip.server.name + ) + self._mark_as_changed() + self.hcloud_floating_ip = None + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + description={"type": "str"}, + server={"type": "str"}, + home_location={"type": "str"}, + force={"type": "bool"}, + type={"choices": ["ipv4", "ipv6"]}, + labels={"type": "dict"}, + delete_protection={"type": "bool"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + required_one_of=[['id', 'name']], + mutually_exclusive=[['home_location', 'server']], + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudFloatingIP.define_module() + + hcloud = AnsibleHcloudFloatingIP(module) + state = module.params["state"] + if state == "absent": + hcloud.delete_floating_ip() + elif state == "present": + hcloud.present_floating_ip() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_facts.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_facts.py new file mode 100644 index 00000000..ea335d16 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_facts.py @@ -0,0 +1,190 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_floating_ip_info + +short_description: Gather infos about the Hetzner Cloud Floating IPs. + +description: + - Gather facts about your Hetzner Cloud Floating IPs. + - This module was called C(hcloud_floating_ip_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_floating_ip_facts). + Note that the M(hetzner.hcloud.hcloud_floating_ip_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_floating_ip_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the Floating IP you want to get. + type: int + label_selector: + description: + - The label selector for the Floating IP you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud Floating ip infos + hcloud_floating_ip_info: + register: output +- name: Print the gathered infos + debug: + var: output +""" + +RETURN = """ +hcloud_floating_ip_info: + description: The Floating ip infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the Floating IP + returned: always + type: int + sample: 1937415 + name: + description: Name of the Floating IP + returned: Always + type: str + sample: my-floating-ip + version_added: "0.1.0" + description: + description: Description of the Floating IP + returned: always + type: str + sample: Falkenstein DC 8 + ip: + description: IP address of the Floating IP + returned: always + type: str + sample: 131.232.99.1 + type: + description: Type of the Floating IP + returned: always + type: str + sample: ipv4 + server: + description: Name of the server where the Floating IP is assigned to. + returned: always + type: str + sample: my-server + home_location: + description: Location the Floating IP was created in + returned: always + type: str + sample: fsn1 + delete_protection: + description: True if the Floating IP is protected for deletion + returned: always + type: bool + version_added: "0.1.0" + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudFloatingIPInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_floating_ip_info") + self.hcloud_floating_ip_info = None + + def _prepare_result(self): + tmp = [] + + for floating_ip in self.hcloud_floating_ip_info: + if floating_ip is not None: + server_name = None + if floating_ip.server is not None: + server_name = floating_ip.server.name + tmp.append({ + "id": to_native(floating_ip.id), + "name": to_native(floating_ip.name), + "description": to_native(floating_ip.description), + "ip": to_native(floating_ip.ip), + "type": to_native(floating_ip.type), + "server": to_native(server_name), + "home_location": to_native(floating_ip.home_location.name), + "labels": floating_ip.labels, + "delete_protection": floating_ip.protection["delete"], + }) + + return tmp + + def get_floating_ips(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_floating_ip_info = [self.client.floating_ips.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_floating_ip_info = self.client.floating_ips.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_floating_ip_info = self.client.floating_ips.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudFloatingIPInfo.define_module() + + is_old_facts = module._name == 'hcloud_floating_ip_facts' + if is_old_facts: + module.deprecate("The 'hcloud_floating_ip_facts' module has been renamed to 'hcloud_floating_ip_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudFloatingIPInfo(module) + + hcloud.get_floating_ips() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_floating_ip_facts': result['hcloud_floating_ip_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_floating_ip_info': result['hcloud_floating_ip_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_info.py new file mode 100644 index 00000000..ea335d16 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_floating_ip_info.py @@ -0,0 +1,190 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_floating_ip_info + +short_description: Gather infos about the Hetzner Cloud Floating IPs. + +description: + - Gather facts about your Hetzner Cloud Floating IPs. + - This module was called C(hcloud_floating_ip_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_floating_ip_facts). + Note that the M(hetzner.hcloud.hcloud_floating_ip_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_floating_ip_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the Floating IP you want to get. + type: int + label_selector: + description: + - The label selector for the Floating IP you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud Floating ip infos + hcloud_floating_ip_info: + register: output +- name: Print the gathered infos + debug: + var: output +""" + +RETURN = """ +hcloud_floating_ip_info: + description: The Floating ip infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the Floating IP + returned: always + type: int + sample: 1937415 + name: + description: Name of the Floating IP + returned: Always + type: str + sample: my-floating-ip + version_added: "0.1.0" + description: + description: Description of the Floating IP + returned: always + type: str + sample: Falkenstein DC 8 + ip: + description: IP address of the Floating IP + returned: always + type: str + sample: 131.232.99.1 + type: + description: Type of the Floating IP + returned: always + type: str + sample: ipv4 + server: + description: Name of the server where the Floating IP is assigned to. + returned: always + type: str + sample: my-server + home_location: + description: Location the Floating IP was created in + returned: always + type: str + sample: fsn1 + delete_protection: + description: True if the Floating IP is protected for deletion + returned: always + type: bool + version_added: "0.1.0" + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudFloatingIPInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_floating_ip_info") + self.hcloud_floating_ip_info = None + + def _prepare_result(self): + tmp = [] + + for floating_ip in self.hcloud_floating_ip_info: + if floating_ip is not None: + server_name = None + if floating_ip.server is not None: + server_name = floating_ip.server.name + tmp.append({ + "id": to_native(floating_ip.id), + "name": to_native(floating_ip.name), + "description": to_native(floating_ip.description), + "ip": to_native(floating_ip.ip), + "type": to_native(floating_ip.type), + "server": to_native(server_name), + "home_location": to_native(floating_ip.home_location.name), + "labels": floating_ip.labels, + "delete_protection": floating_ip.protection["delete"], + }) + + return tmp + + def get_floating_ips(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_floating_ip_info = [self.client.floating_ips.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_floating_ip_info = self.client.floating_ips.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_floating_ip_info = self.client.floating_ips.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudFloatingIPInfo.define_module() + + is_old_facts = module._name == 'hcloud_floating_ip_facts' + if is_old_facts: + module.deprecate("The 'hcloud_floating_ip_facts' module has been renamed to 'hcloud_floating_ip_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudFloatingIPInfo(module) + + hcloud.get_floating_ips() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_floating_ip_facts': result['hcloud_floating_ip_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_floating_ip_info': result['hcloud_floating_ip_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_facts.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_facts.py new file mode 100644 index 00000000..658c0fa1 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_facts.py @@ -0,0 +1,203 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_image_info + +short_description: Gather infos about your Hetzner Cloud images. + + +description: + - Gather infos about your Hetzner Cloud images. + - This module was called C(hcloud_location_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_location_facts). + Note that the M(hetzner.hcloud.hcloud_image_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_image_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the image you want to get. + type: int + name: + description: + - The name of the image you want to get. + type: str + label_selector: + description: + - The label selector for the images you want to get. + type: str + type: + description: + - The label selector for the images you want to get. + default: system + choices: [ system, snapshot, backup ] + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud image infos + hcloud_image_info: + register: output + +- name: Print the gathered infos + debug: + var: output +""" + +RETURN = """ +hcloud_image_info: + description: The image infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the image + returned: always + type: int + sample: 1937415 + type: + description: Type of the image + returned: always + type: str + sample: system + status: + description: Status of the image + returned: always + type: str + sample: available + name: + description: Name of the image + returned: always + type: str + sample: ubuntu-18.04 + description: + description: Detail description of the image + returned: always + type: str + sample: Ubuntu 18.04 Standard 64 bit + os_flavor: + description: OS flavor of the image + returned: always + type: str + sample: ubuntu + os_version: + description: OS version of the image + returned: always + type: str + sample: 18.04 + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudImageInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_image_info") + self.hcloud_image_info = None + + def _prepare_result(self): + tmp = [] + + for image in self.hcloud_image_info: + if image is not None: + tmp.append({ + "id": to_native(image.id), + "status": to_native(image.status), + "type": to_native(image.type), + "name": to_native(image.name), + "description": to_native(image.description), + "os_flavor": to_native(image.os_flavor), + "os_version": to_native(image.os_version), + "labels": image.labels, + }) + return tmp + + def get_images(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_image_info = [self.client.images.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_image_info = [self.client.images.get_by_name( + self.module.params.get("name") + )] + else: + params = {} + label_selector = self.module.params.get("label_selector") + if label_selector: + params["label_selector"] = label_selector + + image_type = self.module.params.get("type") + if image_type: + params["type"] = image_type + + self.hcloud_image_info = self.client.images.get_all(**params) + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + type={"choices": ["system", "snapshot", "backup"], "default": "system", "type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudImageInfo.define_module() + + is_old_facts = module._name == 'hcloud_image_facts' + if is_old_facts: + module.deprecate("The 'hcloud_image_facts' module has been renamed to 'hcloud_image_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudImageInfo(module) + hcloud.get_images() + result = hcloud.get_result() + + if is_old_facts: + ansible_info = { + 'hcloud_imagen_facts': result['hcloud_image_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_image_info': result['hcloud_image_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_info.py new file mode 100644 index 00000000..658c0fa1 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_image_info.py @@ -0,0 +1,203 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_image_info + +short_description: Gather infos about your Hetzner Cloud images. + + +description: + - Gather infos about your Hetzner Cloud images. + - This module was called C(hcloud_location_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_location_facts). + Note that the M(hetzner.hcloud.hcloud_image_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_image_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the image you want to get. + type: int + name: + description: + - The name of the image you want to get. + type: str + label_selector: + description: + - The label selector for the images you want to get. + type: str + type: + description: + - The label selector for the images you want to get. + default: system + choices: [ system, snapshot, backup ] + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud image infos + hcloud_image_info: + register: output + +- name: Print the gathered infos + debug: + var: output +""" + +RETURN = """ +hcloud_image_info: + description: The image infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the image + returned: always + type: int + sample: 1937415 + type: + description: Type of the image + returned: always + type: str + sample: system + status: + description: Status of the image + returned: always + type: str + sample: available + name: + description: Name of the image + returned: always + type: str + sample: ubuntu-18.04 + description: + description: Detail description of the image + returned: always + type: str + sample: Ubuntu 18.04 Standard 64 bit + os_flavor: + description: OS flavor of the image + returned: always + type: str + sample: ubuntu + os_version: + description: OS version of the image + returned: always + type: str + sample: 18.04 + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudImageInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_image_info") + self.hcloud_image_info = None + + def _prepare_result(self): + tmp = [] + + for image in self.hcloud_image_info: + if image is not None: + tmp.append({ + "id": to_native(image.id), + "status": to_native(image.status), + "type": to_native(image.type), + "name": to_native(image.name), + "description": to_native(image.description), + "os_flavor": to_native(image.os_flavor), + "os_version": to_native(image.os_version), + "labels": image.labels, + }) + return tmp + + def get_images(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_image_info = [self.client.images.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_image_info = [self.client.images.get_by_name( + self.module.params.get("name") + )] + else: + params = {} + label_selector = self.module.params.get("label_selector") + if label_selector: + params["label_selector"] = label_selector + + image_type = self.module.params.get("type") + if image_type: + params["type"] = image_type + + self.hcloud_image_info = self.client.images.get_all(**params) + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + type={"choices": ["system", "snapshot", "backup"], "default": "system", "type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudImageInfo.define_module() + + is_old_facts = module._name == 'hcloud_image_facts' + if is_old_facts: + module.deprecate("The 'hcloud_image_facts' module has been renamed to 'hcloud_image_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudImageInfo(module) + hcloud.get_images() + result = hcloud.get_result() + + if is_old_facts: + ansible_info = { + 'hcloud_imagen_facts': result['hcloud_image_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_image_info': result['hcloud_image_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer.py new file mode 100644 index 00000000..6e080545 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer.py @@ -0,0 +1,323 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_load_balancer + +short_description: Create and manage cloud Load Balancers on the Hetzner Cloud. + + +description: + - Create, update and manage cloud Load Balancers on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@LKaemmerling) +version_added: 0.1.0 +options: + id: + description: + - The ID of the Hetzner Cloud Load Balancer to manage. + - Only required if no Load Balancer I(name) is given + type: int + name: + description: + - The Name of the Hetzner Cloud Load Balancer to manage. + - Only required if no Load Balancer I(id) is given or a Load Balancer does not exists. + type: str + load_balancer_type: + description: + - The Load Balancer Type of the Hetzner Cloud Load Balancer to manage. + - Required if Load Balancer does not exists. + type: str + location: + description: + - Location of Load Balancer. + - Required if no I(network_zone) is given and Load Balancer does not exists. + type: str + network_zone: + description: + - Network Zone of Load Balancer. + - Required of no I(location) is given and Load Balancer does not exists. + type: str + labels: + description: + - User-defined labels (key-value pairs). + type: dict + disable_public_interface: + description: + - Disables the public interface. + type: bool + default: False + delete_protection: + description: + - Protect the Load Balancer for deletion. + type: bool + state: + description: + - State of the Load Balancer. + default: present + choices: [ absent, present ] + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +requirements: + - hcloud-python >= 1.8.0 +''' + +EXAMPLES = """ +- name: Create a basic Load Balancer + hcloud_load_balancer: + name: my-Load Balancer + load_balancer_type: lb11 + location: fsn1 + state: present + +- name: Ensure the Load Balancer is absent (remove if needed) + hcloud_load_balancer: + name: my-Load Balancer + state: absent + +""" + +RETURN = """ +hcloud_load_balancer: + description: The Load Balancer instance + returned: Always + type: complex + contains: + id: + description: Numeric identifier of the Load Balancer + returned: always + type: int + sample: 1937415 + name: + description: Name of the Load Balancer + returned: always + type: str + sample: my-Load-Balancer + status: + description: Status of the Load Balancer + returned: always + type: str + sample: running + load_balancer_type: + description: Name of the Load Balancer type of the Load Balancer + returned: always + type: str + sample: cx11 + ipv4_address: + description: Public IPv4 address of the Load Balancer + returned: always + type: str + sample: 116.203.104.109 + ipv6_address: + description: Public IPv6 address of the Load Balancer + returned: always + type: str + sample: 2a01:4f8:1c1c:c140::1 + location: + description: Name of the location of the Load Balancer + returned: always + type: str + sample: fsn1 + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict + delete_protection: + description: True if Load Balancer is protected for deletion + type: bool + returned: always + sample: false + disable_public_interface: + description: True if Load Balancer public interface is disabled + type: bool + returned: always + sample: false +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud.load_balancers.domain import LoadBalancer + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudLoadBalancer(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_load_balancer") + self.hcloud_load_balancer = None + + def _prepare_result(self): + private_ipv4_address = None if len(self.hcloud_load_balancer.private_net) == 0 else to_native( + self.hcloud_load_balancer.private_net[0].ip) + return { + "id": to_native(self.hcloud_load_balancer.id), + "name": to_native(self.hcloud_load_balancer.name), + "ipv4_address": to_native(self.hcloud_load_balancer.public_net.ipv4.ip), + "ipv6_address": to_native(self.hcloud_load_balancer.public_net.ipv6.ip), + "private_ipv4_address": private_ipv4_address, + "load_balancer_type": to_native(self.hcloud_load_balancer.load_balancer_type.name), + "location": to_native(self.hcloud_load_balancer.location.name), + "labels": self.hcloud_load_balancer.labels, + "delete_protection": self.hcloud_load_balancer.protection["delete"], + "disable_public_interface": False if self.hcloud_load_balancer.public_net.enabled else True, + } + + def _get_load_balancer(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_load_balancer = self.client.load_balancers.get_by_id( + self.module.params.get("id") + ) + else: + self.hcloud_load_balancer = self.client.load_balancers.get_by_name( + self.module.params.get("name") + ) + except APIException as e: + self.module.fail_json(msg=e.message) + + def _create_load_balancer(self): + + self.module.fail_on_missing_params( + required_params=["name", "load_balancer_type"] + ) + + params = { + "name": self.module.params.get("name"), + "load_balancer_type": self.client.load_balancer_types.get_by_name( + self.module.params.get("load_balancer_type") + ), + "labels": self.module.params.get("labels"), + } + + if self.module.params.get("location") is None and self.module.params.get("network_zone") is None: + self.module.fail_json(msg="one of the following is required: location, network_zone") + elif self.module.params.get("location") is not None and self.module.params.get("network_zone") is None: + params["location"] = self.client.locations.get_by_name( + self.module.params.get("location") + ) + elif self.module.params.get("location") is None and self.module.params.get("network_zone") is not None: + params["network_zone"] = self.module.params.get("network_zone") + + if not self.module.check_mode: + resp = self.client.load_balancers.create(**params) + resp.action.wait_until_finished(max_retries=1000) + + delete_protection = self.module.params.get("delete_protection") + if delete_protection is not None: + self._get_load_balancer() + self.hcloud_load_balancer.change_protection(delete=delete_protection).wait_until_finished() + + self._mark_as_changed() + self._get_load_balancer() + + def _update_load_balancer(self): + try: + labels = self.module.params.get("labels") + if labels is not None and labels != self.hcloud_load_balancer.labels: + if not self.module.check_mode: + self.hcloud_load_balancer.update(labels=labels) + self._mark_as_changed() + + delete_protection = self.module.params.get("delete_protection") + if delete_protection is not None and delete_protection != self.hcloud_load_balancer.protection["delete"]: + if not self.module.check_mode: + self.hcloud_load_balancer.change_protection(delete=delete_protection).wait_until_finished() + self._mark_as_changed() + self._get_load_balancer() + + disable_public_interface = self.module.params.get("disable_public_interface") + if disable_public_interface is not None and disable_public_interface != (not self.hcloud_load_balancer.public_net.enabled): + if not self.module.check_mode: + if disable_public_interface is True: + self.hcloud_load_balancer.disable_public_interface().wait_until_finished() + else: + self.hcloud_load_balancer.enable_public_interface().wait_until_finished() + self._mark_as_changed() + + load_balancer_type = self.module.params.get("load_balancer_type") + if load_balancer_type is not None and self.hcloud_load_balancer.load_balancer_type.name != load_balancer_type: + new_load_balancer_type = self.client.load_balancer_types.get_by_name(load_balancer_type) + if not new_load_balancer_type: + self.module.fail_json(msg="unknown load balancer type") + if not self.module.check_mode: + self.hcloud_load_balancer.change_type( + load_balancer_type=new_load_balancer_type, + ).wait_until_finished(max_retries=1000) + + self._mark_as_changed() + self._get_load_balancer() + except APIException as e: + self.module.fail_json(msg=e.message) + + def present_load_balancer(self): + self._get_load_balancer() + if self.hcloud_load_balancer is None: + self._create_load_balancer() + else: + self._update_load_balancer() + + def delete_load_balancer(self): + try: + self._get_load_balancer() + if self.hcloud_load_balancer is not None: + if not self.module.check_mode: + self.client.load_balancers.delete(self.hcloud_load_balancer) + self._mark_as_changed() + self.hcloud_load_balancer = None + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + load_balancer_type={"type": "str"}, + location={"type": "str"}, + network_zone={"type": "str"}, + labels={"type": "dict"}, + delete_protection={"type": "bool"}, + disable_public_interface={"type": "bool", "default": False}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + required_one_of=[['id', 'name']], + mutually_exclusive=[["location", "network_zone"]], + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudLoadBalancer.define_module() + + hcloud = AnsibleHcloudLoadBalancer(module) + state = module.params.get("state") + if state == "absent": + hcloud.delete_load_balancer() + elif state == "present": + hcloud.present_load_balancer() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_info.py new file mode 100644 index 00000000..b9463f50 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_info.py @@ -0,0 +1,403 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_load_balancer_info + +short_description: Gather infos about your Hetzner Cloud Load Balancers. + + +description: + - Gather infos about your Hetzner Cloud Load Balancers.. + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the Load Balancers you want to get. + type: int + name: + description: + - The name of the Load Balancers you want to get. + type: str + label_selector: + description: + - The label selector for the Load Balancers you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud load_balancer infos + hcloud_load_balancer_info: + register: output + +- name: Print the gathered infos + debug: + var: output +""" + +RETURN = """ +hcloud_load_balancer_info: + description: The load_balancer infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the Load Balancer + returned: always + type: int + sample: 1937415 + name: + description: Name of the Load Balancer + returned: always + type: str + sample: my-Load-Balancer + status: + description: Status of the Load Balancer + returned: always + type: str + sample: running + load_balancer_type: + description: Name of the Load Balancer type of the Load Balancer + returned: always + type: str + sample: cx11 + ipv4_address: + description: Public IPv4 address of the Load Balancer + returned: always + type: str + sample: 116.203.104.109 + ipv6_address: + description: Public IPv6 address of the Load Balancer + returned: always + type: str + sample: 2a01:4f8:1c1c:c140::1 + location: + description: Name of the location of the Load Balancer + returned: always + type: str + sample: fsn1 + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict + delete_protection: + description: True if Load Balancer is protected for deletion + type: bool + returned: always + sample: false + disable_public_interface: + description: True if Load Balancer public interface is disabled + type: bool + returned: always + sample: false + targets: + description: The targets of the Load Balancer + returned: always + type: complex + contains: + type: + description: Type of the Load Balancer Target + type: str + returned: always + sample: server + load_balancer: + description: Name of the Load Balancer + type: str + returned: always + sample: my-LoadBalancer + server: + description: Name of the Server + type: str + returned: if I(type) is server + sample: my-server + label_selector: + description: Label Selector + type: str + returned: if I(type) is label_selector + sample: application=backend + ip: + description: IP of the dedicated server + type: str + returned: if I(type) is ip + sample: 127.0.0.1 + use_private_ip: + description: + - Route the traffic over the private IP of the Load Balancer through a Hetzner Cloud Network. + - Load Balancer needs to be attached to a network. See M(hetzner.hcloud.hcloud.hcloud_load_balancer_network) + type: bool + sample: true + returned: always + services: + description: all services from this Load Balancer + returned: Always + type: complex + contains: + listen_port: + description: The port the service listens on, i.e. the port users can connect to. + returned: always + type: int + sample: 443 + protocol: + description: Protocol of the service + returned: always + type: str + sample: http + destination_port: + description: + - The port traffic is forwarded to, i.e. the port the targets are listening and accepting connections on. + returned: always + type: int + sample: 80 + proxyprotocol: + description: + - Enable the PROXY protocol. + returned: always + type: bool + sample: false + http: + description: Configuration for HTTP and HTTPS services + returned: always + type: complex + contains: + cookie_name: + description: Name of the cookie which will be set when you enable sticky sessions + returned: always + type: str + sample: HCLBSTICKY + cookie_lifetime: + description: Lifetime of the cookie which will be set when you enable sticky sessions, in seconds + returned: always + type: int + sample: 3600 + certificates: + description: List of Names or IDs of certificates + returned: always + type: list + elements: str + sticky_sessions: + description: Enable or disable sticky_sessions + returned: always + type: bool + sample: true + redirect_http: + description: Redirect Traffic from Port 80 to Port 443, only available if protocol is https + returned: always + type: bool + sample: false + health_check: + description: Configuration for health checks + returned: always + type: complex + contains: + protocol: + description: Protocol the health checks will be performed over + returned: always + type: str + sample: http + port: + description: Port the health check will be performed on + returned: always + type: int + sample: 80 + interval: + description: Interval of health checks, in seconds + returned: always + type: int + sample: 15 + timeout: + description: Timeout of health checks, in seconds + returned: always + type: int + sample: 10 + retries: + description: Number of retries until a target is marked as unhealthy + returned: always + type: int + sample: 3 + http: + description: Additional Configuration of health checks with protocol http/https + returned: always + type: complex + contains: + domain: + description: Domain we will set within the HTTP HOST header + returned: always + type: str + sample: example.com + path: + description: Path we will try to access + returned: always + type: str + sample: / + response: + description: Response we expect, if response is not within the health check response the target is unhealthy + returned: always + type: str + status_codes: + description: List of HTTP status codes we expect to get when we perform the health check. + returned: always + type: list + elements: str + sample: ["2??","3??"] + tls: + description: Verify the TLS certificate, only available if health check protocol is https + returned: always + type: bool + sample: false +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudLoadBalancerInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_load_balancer_info") + self.hcloud_load_balancer_info = None + + def _prepare_result(self): + tmp = [] + + for load_balancer in self.hcloud_load_balancer_info: + if load_balancer is not None: + services = [self._prepare_service_result(service) for service in load_balancer.services] + targets = [self._prepare_target_result(target) for target in load_balancer.targets] + + private_ipv4_address = None if len(load_balancer.private_net) == 0 else to_native( + load_balancer.private_net[0].ip) + tmp.append({ + "id": to_native(load_balancer.id), + "name": to_native(load_balancer.name), + "ipv4_address": to_native(load_balancer.public_net.ipv4.ip), + "ipv6_address": to_native(load_balancer.public_net.ipv6.ip), + "private_ipv4_address": private_ipv4_address, + "load_balancer_type": to_native(load_balancer.load_balancer_type.name), + "location": to_native(load_balancer.location.name), + "labels": load_balancer.labels, + "delete_protection": load_balancer.protection["delete"], + "disable_public_interface": False if load_balancer.public_net.enabled else True, + "targets": targets, + "services": services + }) + return tmp + + @staticmethod + def _prepare_service_result(service): + http = None + if service.protocol != "tcp": + http = { + "cookie_name": to_native(service.http.cookie_name), + "cookie_lifetime": service.http.cookie_name, + "redirect_http": service.http.redirect_http, + "sticky_sessions": service.http.sticky_sessions, + "certificates": [to_native(certificate.name) for certificate in + service.http.certificates], + } + health_check = { + "protocol": to_native(service.health_check.protocol), + "port": service.health_check.port, + "interval": service.health_check.interval, + "timeout": service.health_check.timeout, + "retries": service.health_check.retries, + } + if service.health_check.protocol != "tcp": + health_check["http"] = { + "domain": to_native(service.health_check.http.domain), + "path": to_native(service.health_check.http.path), + "response": to_native(service.health_check.http.response), + "certificates": [to_native(status_code) for status_code in + service.health_check.http.status_codes], + "tls": service.health_check.http.tls, + } + return { + "protocol": to_native(service.protocol), + "listen_port": service.listen_port, + "destination_port": service.destination_port, + "proxyprotocol": service.proxyprotocol, + "http": http, + "health_check": health_check, + } + + @staticmethod + def _prepare_target_result(target): + result = { + "type": to_native(target.type), + "use_private_ip": target.use_private_ip + } + if target.type == "server": + result["server"] = to_native(target.server.name) + elif target.type == "label_selector": + result["label_selector"] = to_native(target.label_selector.selector) + elif target.type == "ip": + result["ip"] = to_native(target.ip.ip) + return result + + def get_load_balancers(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_load_balancer_info = [self.client.load_balancers.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_load_balancer_info = [self.client.load_balancers.get_by_name( + self.module.params.get("name") + )] + else: + params = {} + label_selector = self.module.params.get("label_selector") + if label_selector: + params["label_selector"] = label_selector + + self.hcloud_load_balancer_info = self.client.load_balancers.get_all(**params) + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudLoadBalancerInfo.define_module() + + hcloud = AnsibleHcloudLoadBalancerInfo(module) + hcloud.get_load_balancers() + result = hcloud.get_result() + + ansible_info = { + 'hcloud_load_balancer_info': result['hcloud_load_balancer_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_network.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_network.py new file mode 100644 index 00000000..542c3e86 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_network.py @@ -0,0 +1,201 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_load_balancer_network + +short_description: Manage the relationship between Hetzner Cloud Networks and Load Balancers + + +description: + - Create and delete the relationship Hetzner Cloud Networks and Load Balancers + +author: + - Lukas Kaemmerling (@lkaemmerling) +version_added: 0.1.0 +options: + network: + description: + - The name of the Hetzner Cloud Networks. + type: str + required: true + load_balancer: + description: + - The name of the Hetzner Cloud Load Balancer. + type: str + required: true + ip: + description: + - The IP the Load Balancer should have. + type: str + state: + description: + - State of the load_balancer_network. + default: present + choices: [ absent, present ] + type: str + +requirements: + - hcloud-python >= 1.8.1 + +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic Load Balancer network + hcloud_load_balancer_network: + network: my-network + load_balancer: my-LoadBalancer + state: present + +- name: Create a Load Balancer network and specify the ip address + hcloud_load_balancer_network: + network: my-network + load_balancer: my-LoadBalancer + ip: 10.0.0.1 + state: present + +- name: Ensure the Load Balancer network is absent (remove if needed) + hcloud_load_balancer_network: + network: my-network + load_balancer: my-LoadBalancer + state: absent +""" + +RETURN = """ +hcloud_load_balancer_network: + description: The relationship between a Load Balancer and a network + returned: always + type: complex + contains: + network: + description: Name of the Network + type: str + returned: always + sample: my-network + load_balancer: + description: Name of the Load Balancer + type: str + returned: always + sample: my-LoadBalancer + ip: + description: IP of the Load Balancer within the Network ip range + type: str + returned: always + sample: 10.0.0.8 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + NetworkSubnet = None + + +class AnsibleHcloudLoadBalancerNetwork(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_load_balancer_network") + self.hcloud_network = None + self.hcloud_load_balancer = None + self.hcloud_load_balancer_network = None + + def _prepare_result(self): + return { + "network": to_native(self.hcloud_network.name), + "load_balancer": to_native(self.hcloud_load_balancer.name), + "ip": to_native(self.hcloud_load_balancer_network.ip), + } + + def _get_load_balancer_and_network(self): + try: + self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("network")) + self.hcloud_load_balancer = self.client.load_balancers.get_by_name(self.module.params.get("load_balancer")) + self.hcloud_load_balancer_network = None + except APIException as e: + self.module.fail_json(msg=e.message) + + def _get_load_balancer_network(self): + for privateNet in self.hcloud_load_balancer.private_net: + if privateNet.network.id == self.hcloud_network.id: + self.hcloud_load_balancer_network = privateNet + + def _create_load_balancer_network(self): + params = { + "network": self.hcloud_network + } + + if self.module.params.get("ip") is not None: + params["ip"] = self.module.params.get("ip") + + if not self.module.check_mode: + try: + self.hcloud_load_balancer.attach_to_network(**params).wait_until_finished() + except APIException as e: + self.module.fail_json(msg=e.message) + + self._mark_as_changed() + self._get_load_balancer_and_network() + self._get_load_balancer_network() + + def present_load_balancer_network(self): + self._get_load_balancer_and_network() + self._get_load_balancer_network() + if self.hcloud_load_balancer_network is None: + self._create_load_balancer_network() + + def delete_load_balancer_network(self): + self._get_load_balancer_and_network() + self._get_load_balancer_network() + if self.hcloud_load_balancer_network is not None and self.hcloud_load_balancer is not None: + if not self.module.check_mode: + self.hcloud_load_balancer.detach_from_network( + self.hcloud_load_balancer_network.network).wait_until_finished() + self._mark_as_changed() + self.hcloud_load_balancer_network = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + network={"type": "str", "required": True}, + load_balancer={"type": "str", "required": True}, + ip={"type": "str"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudLoadBalancerNetwork.define_module() + + hcloud = AnsibleHcloudLoadBalancerNetwork(module) + state = module.params["state"] + if state == "absent": + hcloud.delete_load_balancer_network() + elif state == "present": + hcloud.present_load_balancer_network() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_service.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_service.py new file mode 100644 index 00000000..4ef46346 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_service.py @@ -0,0 +1,613 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_load_balancer_service + +short_description: Create and manage the services of cloud Load Balancers on the Hetzner Cloud. + + +description: + - Create, update and manage the services of cloud Load Balancers on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@LKaemmerling) +version_added: 0.1.0 +options: + load_balancer: + description: + - The Name of the Hetzner Cloud Load Balancer the service belongs to + type: str + required: true + listen_port: + description: + - The port the service listens on, i.e. the port users can connect to. + type: int + required: true + destination_port: + description: + - The port traffic is forwarded to, i.e. the port the targets are listening and accepting connections on. + - Required if services does not exists and protocol is tcp. + type: int + protocol: + description: + - Protocol of the service. + - Required if Load Balancer does not exists. + type: str + choices: [ http, https, tcp ] + proxyprotocol: + description: + - Enable the PROXY protocol. + type: bool + default: False + http: + description: + - Configuration for HTTP and HTTPS services + type: dict + suboptions: + cookie_name: + description: + - Name of the cookie which will be set when you enable sticky sessions + type: str + cookie_lifetime: + description: + - Lifetime of the cookie which will be set when you enable sticky sessions, in seconds + type: int + certificates: + description: + - List of Names or IDs of certificates + type: list + elements: str + sticky_sessions: + description: + - Enable or disable sticky_sessions + type: bool + default: False + redirect_http: + description: + - Redirect Traffic from Port 80 to Port 443, only available if protocol is https + type: bool + default: False + health_check: + description: + - Configuration for health checks + type: dict + suboptions: + protocol: + description: + - Protocol the health checks will be performed over + type: str + choices: [ http, https, tcp ] + port: + description: + - Port the health check will be performed on + type: int + interval: + description: + - Interval of health checks, in seconds + type: int + timeout: + description: + - Timeout of health checks, in seconds + type: int + retries: + description: + - Number of retries until a target is marked as unhealthy + type: int + http: + description: + - Additional Configuration of health checks with protocol http/https + type: dict + suboptions: + domain: + description: + - Domain we will set within the HTTP HOST header + type: str + path: + description: + - Path we will try to access + type: str + response: + description: + - Response we expect, if response is not within the health check response the target is unhealthy + type: str + status_codes: + description: + - List of HTTP status codes we expect to get when we perform the health check. + type: list + elements: str + tls: + description: + - Verify the TLS certificate, only available if health check protocol is https + type: bool + default: False + state: + description: + - State of the Load Balancer. + default: present + choices: [ absent, present ] + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +requirements: + - hcloud-python >= 1.8.1 +''' + +EXAMPLES = """ +- name: Create a basic Load Balancer service with Port 80 + hcloud_load_balancer_service: + load_balancer: my-load-balancer + protocol: http + listen_port: 80 + state: present + +- name: Ensure the Load Balancer is absent (remove if needed) + hcloud_load_balancer_service: + load_balancer: my-Load Balancer + protocol: http + listen_port: 80 + state: absent +""" + +RETURN = """ +hcloud_load_balancer_service: + description: The Load Balancer service instance + returned: Always + type: complex + contains: + load_balancer: + description: The name of the Load Balancer where the service belongs to + returned: always + type: str + sample: my-load-balancer + listen_port: + description: The port the service listens on, i.e. the port users can connect to. + returned: always + type: int + sample: 443 + protocol: + description: Protocol of the service + returned: always + type: str + sample: http + destination_port: + description: + - The port traffic is forwarded to, i.e. the port the targets are listening and accepting connections on. + returned: always + type: int + sample: 80 + proxyprotocol: + description: + - Enable the PROXY protocol. + returned: always + type: bool + sample: false + http: + description: Configuration for HTTP and HTTPS services + returned: always + type: complex + contains: + cookie_name: + description: Name of the cookie which will be set when you enable sticky sessions + returned: always + type: str + sample: HCLBSTICKY + cookie_lifetime: + description: Lifetime of the cookie which will be set when you enable sticky sessions, in seconds + returned: always + type: int + sample: 3600 + certificates: + description: List of Names or IDs of certificates + returned: always + type: list + elements: str + sticky_sessions: + description: Enable or disable sticky_sessions + returned: always + type: bool + sample: true + redirect_http: + description: Redirect Traffic from Port 80 to Port 443, only available if protocol is https + returned: always + type: bool + sample: false + health_check: + description: Configuration for health checks + returned: always + type: complex + contains: + protocol: + description: Protocol the health checks will be performed over + returned: always + type: str + sample: http + port: + description: Port the health check will be performed on + returned: always + type: int + sample: 80 + interval: + description: Interval of health checks, in seconds + returned: always + type: int + sample: 15 + timeout: + description: Timeout of health checks, in seconds + returned: always + type: int + sample: 10 + retries: + description: Number of retries until a target is marked as unhealthy + returned: always + type: int + sample: 3 + http: + description: Additional Configuration of health checks with protocol http/https + returned: always + type: complex + contains: + domain: + description: Domain we will set within the HTTP HOST header + returned: always + type: str + sample: example.com + path: + description: Path we will try to access + returned: always + type: str + sample: / + response: + description: Response we expect, if response is not within the health check response the target is unhealthy + returned: always + type: str + status_codes: + description: List of HTTP status codes we expect to get when we perform the health check. + returned: always + type: list + elements: str + sample: ["2??","3??"] + tls: + description: Verify the TLS certificate, only available if health check protocol is https + returned: always + type: bool + sample: false +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud.load_balancers.domain import LoadBalancer, LoadBalancerService, LoadBalancerServiceHttp, \ + LoadBalancerServiceHealthCheck, LoadBalancerServiceHealthCheckHttp + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudLoadBalancerService(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_load_balancer_service") + self.hcloud_load_balancer = None + self.hcloud_load_balancer_service = None + + def _prepare_result(self): + http = None + if self.hcloud_load_balancer_service.protocol != "tcp": + http = { + "cookie_name": to_native(self.hcloud_load_balancer_service.http.cookie_name), + "cookie_lifetime": self.hcloud_load_balancer_service.http.cookie_name, + "redirect_http": self.hcloud_load_balancer_service.http.redirect_http, + "sticky_sessions": self.hcloud_load_balancer_service.http.sticky_sessions, + "certificates": [to_native(certificate.name) for certificate in + self.hcloud_load_balancer_service.http.certificates], + } + health_check = { + "protocol": to_native(self.hcloud_load_balancer_service.health_check.protocol), + "port": self.hcloud_load_balancer_service.health_check.port, + "interval": self.hcloud_load_balancer_service.health_check.interval, + "timeout": self.hcloud_load_balancer_service.health_check.timeout, + "retries": self.hcloud_load_balancer_service.health_check.retries, + } + if self.hcloud_load_balancer_service.health_check.protocol != "tcp": + health_check["http"] = { + "domain": to_native(self.hcloud_load_balancer_service.health_check.http.domain), + "path": to_native(self.hcloud_load_balancer_service.health_check.http.path), + "response": to_native(self.hcloud_load_balancer_service.health_check.http.response), + "certificates": [to_native(status_code) for status_code in + self.hcloud_load_balancer_service.health_check.http.status_codes], + "tls": self.hcloud_load_balancer_service.health_check.http.tls, + } + return { + "load_balancer": to_native(self.hcloud_load_balancer.name), + "protocol": to_native(self.hcloud_load_balancer_service.protocol), + "listen_port": self.hcloud_load_balancer_service.listen_port, + "destination_port": self.hcloud_load_balancer_service.destination_port, + "proxyprotocol": self.hcloud_load_balancer_service.proxyprotocol, + "http": http, + "health_check": health_check, + } + + def _get_load_balancer(self): + try: + self.hcloud_load_balancer = self.client.load_balancers.get_by_name( + self.module.params.get("load_balancer") + ) + self._get_load_balancer_service() + except APIException as e: + self.module.fail_json(msg=e.message) + + def _create_load_balancer_service(self): + + self.module.fail_on_missing_params( + required_params=["protocol"] + ) + if self.module.params.get("protocol") == "tcp": + self.module.fail_on_missing_params( + required_params=["destination_port"] + ) + + params = { + "protocol": self.module.params.get("protocol"), + "listen_port": self.module.params.get("listen_port"), + "proxyprotocol": self.module.params.get("proxyprotocol") + } + + if self.module.params.get("destination_port"): + params["destination_port"] = self.module.params.get("destination_port") + + if self.module.params.get("http"): + params["http"] = self.__get_service_http(http_arg=self.module.params.get("http")) + + if self.module.params.get("health_check"): + params["health_check"] = self.__get_service_health_checks( + health_check=self.module.params.get("health_check")) + + if not self.module.check_mode: + try: + self.hcloud_load_balancer.add_service(LoadBalancerService(**params)).wait_until_finished( + max_retries=1000) + except APIException as e: + self.module.fail_json(msg=e.message) + self._mark_as_changed() + self._get_load_balancer() + self._get_load_balancer_service() + + def __get_service_http(self, http_arg): + service_http = LoadBalancerServiceHttp(certificates=[]) + if http_arg.get("cookie_name") is not None: + service_http.cookie_name = http_arg.get("cookie_name") + if http_arg.get("cookie_lifetime") is not None: + service_http.cookie_lifetime = http_arg.get("cookie_lifetime") + if http_arg.get("sticky_sessions") is not None: + service_http.sticky_sessions = http_arg.get("sticky_sessions") + if http_arg.get("redirect_http") is not None: + service_http.redirect_http = http_arg.get("redirect_http") + if http_arg.get("certificates") is not None: + certificates = http_arg.get("certificates") + if certificates is not None: + for certificate in certificates: + hcloud_cert = None + try: + try: + hcloud_cert = self.client.certificates.get_by_name( + certificate + ) + except APIException: + hcloud_cert = self.client.certificates.get_by_id( + certificate + ) + except APIException as e: + self.module.fail_json(msg=e.message) + service_http.certificates.append(hcloud_cert) + + return service_http + + def __get_service_health_checks(self, health_check): + service_health_check = LoadBalancerServiceHealthCheck() + if health_check.get("protocol") is not None: + service_health_check.protocol = health_check.get("protocol") + if health_check.get("port") is not None: + service_health_check.port = health_check.get("port") + if health_check.get("interval") is not None: + service_health_check.interval = health_check.get("interval") + if health_check.get("timeout") is not None: + service_health_check.timeout = health_check.get("timeout") + if health_check.get("retries") is not None: + service_health_check.retries = health_check.get("retries") + if health_check.get("http") is not None: + health_check_http = health_check.get("http") + service_health_check.http = LoadBalancerServiceHealthCheckHttp() + if health_check_http.get("domain") is not None: + service_health_check.http.domain = health_check_http.get("domain") + if health_check_http.get("path") is not None: + service_health_check.http.path = health_check_http.get("path") + if health_check_http.get("response") is not None: + service_health_check.http.response = health_check_http.get("response") + if health_check_http.get("status_codes") is not None: + service_health_check.http.status_codes = health_check_http.get("status_codes") + if health_check_http.get("tls") is not None: + service_health_check.http.tls = health_check_http.get("tls") + + return service_health_check + + def _update_load_balancer_service(self): + changed = False + try: + params = { + "listen_port": self.module.params.get("listen_port"), + } + + if self.module.params.get("destination_port") is not None: + if self.hcloud_load_balancer_service.destination_port != self.module.params.get("destination_port"): + params["destination_port"] = self.module.params.get("destination_port") + changed = True + + if self.module.params.get("protocol") is not None: + if self.hcloud_load_balancer_service.protocol != self.module.params.get("protocol"): + params["protocol"] = self.module.params.get("protocol") + changed = True + + if self.module.params.get("proxyprotocol") is not None: + if self.hcloud_load_balancer_service.proxyprotocol != self.module.params.get("proxyprotocol"): + params["proxyprotocol"] = self.module.params.get("proxyprotocol") + changed = True + + if self.module.params.get("http") is not None: + params["http"] = self.__get_service_http(http_arg=self.module.params.get("http")) + changed = True + + if self.module.params.get("health_check") is not None: + params["health_check"] = self.__get_service_health_checks( + health_check=self.module.params.get("health_check")) + changed = True + + if not self.module.check_mode: + self.hcloud_load_balancer.update_service(LoadBalancerService(**params)).wait_until_finished( + max_retries=1000) + except APIException as e: + self.module.fail_json(msg=e.message) + self._get_load_balancer() + + if changed: + self._mark_as_changed() + + def _get_load_balancer_service(self): + for service in self.hcloud_load_balancer.services: + if self.module.params.get("listen_port") == service.listen_port: + self.hcloud_load_balancer_service = service + + def present_load_balancer_service(self): + self._get_load_balancer() + if self.hcloud_load_balancer_service is None: + self._create_load_balancer_service() + else: + self._update_load_balancer_service() + + def delete_load_balancer_service(self): + try: + self._get_load_balancer() + if self.hcloud_load_balancer_service is not None: + if not self.module.check_mode: + self.hcloud_load_balancer.delete_service(self.hcloud_load_balancer_service).wait_until_finished( + max_retries=1000) + self._mark_as_changed() + self.hcloud_load_balancer_service = None + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + load_balancer={"type": "str", "required": True}, + listen_port={"type": "int", "required": True}, + destination_port={"type": "int"}, + protocol={ + "type": "str", + "choices": ["http", "https", "tcp"], + }, + proxyprotocol={"type": "bool", "default": False}, + http={ + "type": "dict", + "options": dict( + cookie_name={ + "type": "str" + }, + cookie_lifetime={ + "type": "int" + }, + sticky_sessions={ + "type": "bool", + "default": False + }, + redirect_http={ + "type": "bool", + "default": False + }, + certificates={ + "type": "list", + "elements": "str" + }, + + ) + }, + health_check={ + "type": "dict", + "options": dict( + protocol={ + "type": "str", + "choices": ["http", "https", "tcp"], + }, + port={ + "type": "int" + }, + interval={ + "type": "int" + }, + timeout={ + "type": "int" + }, + retries={ + "type": "int" + }, + http={ + "type": "dict", + "options": dict( + domain={ + "type": "str" + }, + path={ + "type": "str" + }, + response={ + "type": "str" + }, + status_codes={ + "type": "list", + "elements": "str" + }, + tls={ + "type": "bool", + "default": False + }, + ) + } + ) + + }, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudLoadBalancerService.define_module() + + hcloud = AnsibleHcloudLoadBalancerService(module) + state = module.params.get("state") + if state == "absent": + hcloud.delete_load_balancer_service() + elif state == "present": + hcloud.present_load_balancer_service() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_target.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_target.py new file mode 100644 index 00000000..e1afde8d --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_target.py @@ -0,0 +1,310 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_load_balancer_target + +short_description: Manage Hetzner Cloud Load Balancer targets + + +description: + - Create and delete Hetzner Cloud Load Balancer targets + +author: + - Lukas Kaemmerling (@lkaemmerling) +version_added: 0.1.0 +options: + type: + description: + - The type of the target. + type: str + choices: [ server, label_selector, ip ] + required: true + load_balancer: + description: + - The name of the Hetzner Cloud Load Balancer. + type: str + required: true + server: + description: + - The name of the Hetzner Cloud Server. + - Required if I(type) is server + type: str + label_selector: + description: + - A Label Selector that will be used to determine the targets dynamically + - Required if I(type) is label_selector + type: str + ip: + description: + - An IP from a Hetzner Dedicated Server, needs to belongs to the same user as the project. + - Required if I(type) is ip + type: str + use_private_ip: + description: + - Route the traffic over the private IP of the Load Balancer through a Hetzner Cloud Network. + - Load Balancer needs to be attached to a network. See M(hetzner.hcloud.hcloud.hcloud_load_balancer_network) + type: bool + default: False + state: + description: + - State of the load_balancer_network. + default: present + choices: [ absent, present ] + type: str + +requirements: + - hcloud-python >= 1.8.1 + +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a server Load Balancer target + hcloud_load_balancer_target: + type: server + load_balancer: my-LoadBalancer + server: my-server + state: present + +- name: Create a label_selector Load Balancer target + hcloud_load_balancer_target: + type: server + load_balancer: my-LoadBalancer + label_selector: application=backend + state: present + +- name: Create an IP Load Balancer target + hcloud_load_balancer_target: + type: server + load_balancer: my-LoadBalancer + ip: 127.0.0.1 + state: present + +- name: Ensure the Load Balancer target is absent (remove if needed) + hcloud_load_balancer_target: + type: server + load_balancer: my-LoadBalancer + server: my-server + state: absent +""" + +RETURN = """ +hcloud_load_balancer_target: + description: The relationship between a Load Balancer and a network + returned: always + type: complex + contains: + type: + description: Type of the Load Balancer Target + type: str + returned: always + sample: server + load_balancer: + description: Name of the Load Balancer + type: str + returned: always + sample: my-LoadBalancer + server: + description: Name of the Server + type: str + returned: if I(type) is server + sample: my-server + label_selector: + description: Label Selector + type: str + returned: if I(type) is label_selector + sample: application=backend + ip: + description: IP of the dedicated server + type: str + returned: if I(type) is ip + sample: 127.0.0.1 + use_private_ip: + description: + - Route the traffic over the private IP of the Load Balancer through a Hetzner Cloud Network. + - Load Balancer needs to be attached to a network. See M(hetzner.hcloud.hcloud.hcloud_load_balancer_network) + type: bool + sample: true + returned: always +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException + from hcloud.load_balancers.domain import LoadBalancerTarget, LoadBalancerTargetLabelSelector, LoadBalancerTargetIP +except ImportError: + APIException = None + LoadBalancerTarget = None + LoadBalancerTargetLabelSelector = None + LoadBalancerTargetIP = None + + +class AnsibleHcloudLoadBalancerTarget(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_load_balancer_target") + self.hcloud_load_balancer = None + self.hcloud_load_balancer_target = None + self.hcloud_server = None + + def _prepare_result(self): + result = { + "type": to_native(self.hcloud_load_balancer_target.type), + "load_balancer": to_native(self.hcloud_load_balancer.name), + "use_private_ip": self.hcloud_load_balancer_target.use_private_ip + } + + if self.hcloud_load_balancer_target.type == "server": + result["server"] = to_native(self.hcloud_load_balancer_target.server.name) + elif self.hcloud_load_balancer_target.type == "label_selector": + result["label_selector"] = to_native(self.hcloud_load_balancer_target.label_selector.selector) + elif self.hcloud_load_balancer_target.type == "ip": + result["ip"] = to_native(self.hcloud_load_balancer_target.ip.ip) + return result + + def _get_load_balancer_and_target(self): + try: + self.hcloud_load_balancer = self.client.load_balancers.get_by_name(self.module.params.get("load_balancer")) + if self.module.params.get("type") == "server": + self.hcloud_server = self.client.servers.get_by_name(self.module.params.get("server")) + self.hcloud_load_balancer_target = None + except APIException as e: + self.module.fail_json(msg=e.message) + + def _get_load_balancer_target(self): + for target in self.hcloud_load_balancer.targets: + if self.module.params.get("type") == "server" and target.type == "server": + if target.server.id == self.hcloud_server.id: + self.hcloud_load_balancer_target = target + elif self.module.params.get("type") == "label_selector" and target.type == "label_selector": + if target.label_selector.selector == self.module.params.get("label_selector"): + self.hcloud_load_balancer_target = target + elif self.module.params.get("type") == "ip" and target.type == "ip": + if target.ip.ip == self.module.params.get("ip"): + self.hcloud_load_balancer_target = target + + def _create_load_balancer_target(self): + params = { + "target": None + } + + if self.module.params.get("type") == "server": + self.module.fail_on_missing_params( + required_params=["server"] + ) + params["target"] = LoadBalancerTarget(type=self.module.params.get("type"), server=self.hcloud_server, + use_private_ip=self.module.params.get("use_private_ip")) + elif self.module.params.get("type") == "label_selector": + self.module.fail_on_missing_params( + required_params=["label_selector"] + ) + params["target"] = LoadBalancerTarget(type=self.module.params.get("type"), + label_selector=LoadBalancerTargetLabelSelector( + selector=self.module.params.get("label_selector")), + use_private_ip=self.module.params.get("use_private_ip")) + elif self.module.params.get("type") == "ip": + self.module.fail_on_missing_params( + required_params=["ip"] + ) + params["target"] = LoadBalancerTarget(type=self.module.params.get("type"), + ip=LoadBalancerTargetIP(ip=self.module.params.get("ip")), + use_private_ip=False) + + if not self.module.check_mode: + try: + self.hcloud_load_balancer.add_target(**params).wait_until_finished() + except APIException as e: + if e.code == "locked" or e.code == "conflict": + self._create_load_balancer_target() + else: + self.module.fail_json(msg=e.message) + + self._mark_as_changed() + self._get_load_balancer_and_target() + self._get_load_balancer_target() + + def present_load_balancer_target(self): + self._get_load_balancer_and_target() + self._get_load_balancer_target() + if self.hcloud_load_balancer_target is None: + self._create_load_balancer_target() + + def delete_load_balancer_target(self): + self._get_load_balancer_and_target() + self._get_load_balancer_target() + if self.hcloud_load_balancer_target is not None and self.hcloud_load_balancer is not None: + if not self.module.check_mode: + target = None + if self.module.params.get("type") == "server": + self.module.fail_on_missing_params( + required_params=["server"] + ) + target = LoadBalancerTarget(type=self.module.params.get("type"), + server=self.hcloud_server) + elif self.module.params.get("type") == "label_selector": + self.module.fail_on_missing_params( + required_params=["label_selector"] + ) + target = LoadBalancerTarget(type=self.module.params.get("type"), + label_selector=LoadBalancerTargetLabelSelector( + selector=self.module.params.get("label_selector")), + use_private_ip=self.module.params.get("use_private_ip")) + elif self.module.params.get("type") == "ip": + self.module.fail_on_missing_params( + required_params=["ip"] + ) + target = LoadBalancerTarget(type=self.module.params.get("type"), + ip=LoadBalancerTargetIP(ip=self.module.params.get("ip")), + use_private_ip=False) + self.hcloud_load_balancer.remove_target(target).wait_until_finished() + self._mark_as_changed() + self.hcloud_load_balancer_target = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + type={"type": "str", "required": True, "choices": ["server", "label_selector", "ip"]}, + load_balancer={"type": "str", "required": True}, + server={"type": "str"}, + label_selector={"type": "str"}, + ip={"type": "str"}, + use_private_ip={"type": "bool", "default": False}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudLoadBalancerTarget.define_module() + + hcloud = AnsibleHcloudLoadBalancerTarget(module) + state = module.params["state"] + if state == "absent": + hcloud.delete_load_balancer_target() + elif state == "present": + hcloud.present_load_balancer_target() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_type_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_type_info.py new file mode 100644 index 00000000..96450093 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_load_balancer_type_info.py @@ -0,0 +1,163 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_load_balancer_type_info + +short_description: Gather infos about the Hetzner Cloud Load Balancer types. + + +description: + - Gather infos about your Hetzner Cloud Load Balancer types. + +author: + - Lukas Kaemmerling (@LKaemmerling) +version_added: 0.1.0 +options: + id: + description: + - The ID of the Load Balancer type you want to get. + type: int + name: + description: + - The name of the Load Balancer type you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud Load Balancer type infos + hcloud_load_balancer_type_info: + register: output + +- name: Print the gathered infos + debug: + var: output.hcloud_load_balancer_type_info +""" + +RETURN = """ +hcloud_load_balancer_type_info: + description: The Load Balancer type infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the Load Balancer type + returned: always + type: int + sample: 1937415 + name: + description: Name of the Load Balancer type + returned: always + type: str + sample: lb11 + description: + description: Description of the Load Balancer type + returned: always + type: str + sample: LB11 + max_connections: + description: Number of maximum simultaneous open connections + returned: always + type: int + sample: 1 + max_services: + description: Number of services a Load Balancer of this type can have + returned: always + type: int + sample: 1 + max_targets: + description: Number of targets a single Load Balancer can have + returned: always + type: int + sample: 25 + max_assigned_certificates: + description: Number of SSL Certificates that can be assigned to a single Load Balancer + returned: always + type: int + sample: 5 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + pass + + +class AnsibleHcloudLoadBalancerTypeInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_load_balancer_type_info") + self.hcloud_load_balancer_type_info = None + + def _prepare_result(self): + tmp = [] + + for load_balancer_type in self.hcloud_load_balancer_type_info: + if load_balancer_type is not None: + tmp.append({ + "id": to_native(load_balancer_type.id), + "name": to_native(load_balancer_type.name), + "description": to_native(load_balancer_type.description), + "max_connections": load_balancer_type.max_connections, + "max_services": load_balancer_type.max_services, + "max_targets": load_balancer_type.max_targets, + "max_assigned_certificates": load_balancer_type.max_assigned_certificates + }) + return tmp + + def get_load_balancer_types(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_load_balancer_type_info = [self.client.load_balancer_types.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_load_balancer_type_info = [self.client.load_balancer_types.get_by_name( + self.module.params.get("name") + )] + else: + self.hcloud_load_balancer_type_info = self.client.load_balancer_types.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudLoadBalancerTypeInfo.define_module() + + hcloud = AnsibleHcloudLoadBalancerTypeInfo(module) + hcloud.get_load_balancer_types() + result = hcloud.get_result() + ansible_info = { + 'hcloud_load_balancer_type_info': result['hcloud_load_balancer_type_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_facts.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_facts.py new file mode 100644 index 00000000..21f4774f --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_facts.py @@ -0,0 +1,164 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_location_info + +short_description: Gather infos about your Hetzner Cloud locations. + + +description: + - Gather infos about your Hetzner Cloud locations. + - This module was called C(hcloud_location_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_location_facts). + Note that the M(hetzner.hcloud.hcloud_location_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_location_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the location you want to get. + type: int + name: + description: + - The name of the location you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud location infos + hcloud_location_info: + register: output + +- name: Print the gathered infos + debug: + var: output +""" + +RETURN = """ +hcloud_location_info: + description: The location infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the location + returned: always + type: int + sample: 1937415 + name: + description: Name of the location + returned: always + type: str + sample: fsn1 + description: + description: Detail description of the location + returned: always + type: str + sample: Falkenstein DC Park 1 + country: + description: Country code of the location + returned: always + type: str + sample: DE + city: + description: City of the location + returned: always + type: str + sample: Falkenstein +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudLocationInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_location_info") + self.hcloud_location_info = None + + def _prepare_result(self): + tmp = [] + + for location in self.hcloud_location_info: + if location is not None: + tmp.append({ + "id": to_native(location.id), + "name": to_native(location.name), + "description": to_native(location.description), + "city": to_native(location.city), + "country": to_native(location.country) + }) + return tmp + + def get_locations(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_location_info = [self.client.locations.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_location_info = [self.client.locations.get_by_name( + self.module.params.get("name") + )] + else: + self.hcloud_location_info = self.client.locations.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudLocationInfo.define_module() + + is_old_facts = module._name == 'hcloud_location_facts' + if is_old_facts: + module.deprecate("The 'hcloud_location_info' module has been renamed to 'hcloud_location_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudLocationInfo(module) + hcloud.get_locations() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_location_facts': result['hcloud_location_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_location_info': result['hcloud_location_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_info.py new file mode 100644 index 00000000..21f4774f --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_location_info.py @@ -0,0 +1,164 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_location_info + +short_description: Gather infos about your Hetzner Cloud locations. + + +description: + - Gather infos about your Hetzner Cloud locations. + - This module was called C(hcloud_location_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_location_facts). + Note that the M(hetzner.hcloud.hcloud_location_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_location_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the location you want to get. + type: int + name: + description: + - The name of the location you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud location infos + hcloud_location_info: + register: output + +- name: Print the gathered infos + debug: + var: output +""" + +RETURN = """ +hcloud_location_info: + description: The location infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the location + returned: always + type: int + sample: 1937415 + name: + description: Name of the location + returned: always + type: str + sample: fsn1 + description: + description: Detail description of the location + returned: always + type: str + sample: Falkenstein DC Park 1 + country: + description: Country code of the location + returned: always + type: str + sample: DE + city: + description: City of the location + returned: always + type: str + sample: Falkenstein +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudLocationInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_location_info") + self.hcloud_location_info = None + + def _prepare_result(self): + tmp = [] + + for location in self.hcloud_location_info: + if location is not None: + tmp.append({ + "id": to_native(location.id), + "name": to_native(location.name), + "description": to_native(location.description), + "city": to_native(location.city), + "country": to_native(location.country) + }) + return tmp + + def get_locations(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_location_info = [self.client.locations.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_location_info = [self.client.locations.get_by_name( + self.module.params.get("name") + )] + else: + self.hcloud_location_info = self.client.locations.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudLocationInfo.define_module() + + is_old_facts = module._name == 'hcloud_location_facts' + if is_old_facts: + module.deprecate("The 'hcloud_location_info' module has been renamed to 'hcloud_location_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudLocationInfo(module) + hcloud.get_locations() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_location_facts': result['hcloud_location_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_location_info': result['hcloud_location_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network.py new file mode 100644 index 00000000..f99a7fd5 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network.py @@ -0,0 +1,247 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_network + +short_description: Create and manage cloud Networks on the Hetzner Cloud. + + +description: + - Create, update and manage cloud Networks on the Hetzner Cloud. + - You need at least hcloud-python 1.3.0. + +author: + - Lukas Kaemmerling (@lkaemmerling) + +options: + id: + description: + - The ID of the Hetzner Cloud Networks to manage. + - Only required if no Network I(name) is given. + type: int + name: + description: + - The Name of the Hetzner Cloud Network to manage. + - Only required if no Network I(id) is given or a Network does not exists. + type: str + ip_range: + description: + - IP range of the Network. + - Required if Network does not exists. + type: str + labels: + description: + - User-defined labels (key-value pairs). + type: dict + delete_protection: + description: + - Protect the Network for deletion. + type: bool + state: + description: + - State of the Network. + default: present + choices: [ absent, present ] + type: str + +requirements: + - hcloud-python >= 1.3.0 + +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic network + hcloud_network: + name: my-network + ip_range: 10.0.0.0/8 + state: present + +- name: Ensure the Network is absent (remove if needed) + hcloud_network: + name: my-network + state: absent +""" + +RETURN = """ +hcloud_network: + description: The Network + returned: always + type: complex + contains: + id: + description: ID of the Network + type: int + returned: always + sample: 12345 + name: + description: Name of the Network + type: str + returned: always + sample: my-volume + ip_range: + description: IP range of the Network + type: str + returned: always + sample: 10.0.0.0/8 + delete_protection: + description: True if Network is protected for deletion + type: bool + returned: always + sample: false + version_added: "0.1.0" + labels: + description: User-defined labels (key-value pairs) + type: dict + returned: always + sample: + key: value + mylabel: 123 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudNetwork(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_network") + self.hcloud_network = None + + def _prepare_result(self): + return { + "id": to_native(self.hcloud_network.id), + "name": to_native(self.hcloud_network.name), + "ip_range": to_native(self.hcloud_network.ip_range), + "delete_protection": self.hcloud_network.protection["delete"], + "labels": self.hcloud_network.labels, + } + + def _get_network(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_network = self.client.networks.get_by_id( + self.module.params.get("id") + ) + else: + self.hcloud_network = self.client.networks.get_by_name( + self.module.params.get("name") + ) + except APIException as e: + self.module.fail_json(msg=e.message) + + def _create_network(self): + + self.module.fail_on_missing_params( + required_params=["name", "ip_range"] + ) + params = { + "name": self.module.params.get("name"), + "ip_range": self.module.params.get("ip_range"), + "labels": self.module.params.get("labels"), + } + + if not self.module.check_mode: + self.client.networks.create(**params) + + delete_protection = self.module.params.get("delete_protection") + if delete_protection is not None: + self._get_network() + self.hcloud_network.change_protection(delete=delete_protection).wait_until_finished() + + self._mark_as_changed() + self._get_network() + + def _update_network(self): + try: + labels = self.module.params.get("labels") + if labels is not None and labels != self.hcloud_network.labels: + if not self.module.check_mode: + self.hcloud_network.update(labels=labels) + self._mark_as_changed() + + ip_range = self.module.params.get("ip_range") + if ip_range is not None and ip_range != self.hcloud_network.ip_range: + if not self.module.check_mode: + self.hcloud_network.change_ip_range(ip_range=ip_range).wait_until_finished() + self._mark_as_changed() + + delete_protection = self.module.params.get("delete_protection") + if delete_protection is not None and delete_protection != self.hcloud_network.protection["delete"]: + if not self.module.check_mode: + self.hcloud_network.change_protection(delete=delete_protection).wait_until_finished() + self._mark_as_changed() + except APIException as e: + self.module.fail_json(msg=e.message) + self._get_network() + + def present_network(self): + self._get_network() + if self.hcloud_network is None: + self._create_network() + else: + self._update_network() + + def delete_network(self): + try: + self._get_network() + if self.hcloud_network is not None: + if not self.module.check_mode: + self.client.networks.delete(self.hcloud_network) + self._mark_as_changed() + except APIException as e: + self.module.fail_json(msg=e.message) + self.hcloud_network = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + ip_range={"type": "str"}, + labels={"type": "dict"}, + delete_protection={"type": "bool"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + required_one_of=[['id', 'name']], + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudNetwork.define_module() + + hcloud = AnsibleHcloudNetwork(module) + state = module.params["state"] + if state == "absent": + hcloud.delete_network() + elif state == "present": + hcloud.present_network() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network_info.py new file mode 100644 index 00000000..7eafbdea --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_network_info.py @@ -0,0 +1,295 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_network_info + +short_description: Gather info about your Hetzner Cloud networks. + + +description: + - Gather info about your Hetzner Cloud networks. + +author: + - Christopher Schmitt (@cschmitt-hcloud) + +options: + id: + description: + - The ID of the network you want to get. + type: int + name: + description: + - The name of the network you want to get. + type: str + label_selector: + description: + - The label selector for the network you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud network info + local_action: + module: hcloud_network_info + +- name: Print the gathered info + debug: + var: hcloud_network_info +""" + +RETURN = """ +hcloud_network_info: + description: The network info as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the network + returned: always + type: int + sample: 1937415 + name: + description: Name of the network + returned: always + type: str + sample: awesome-network + ip_range: + description: IP range of the network + returned: always + type: str + sample: 10.0.0.0/16 + subnetworks: + description: Subnetworks belonging to the network + returned: always + type: complex + contains: + type: + description: Type of the subnetwork. + returned: always + type: str + sample: cloud + network_zone: + description: Network of the subnetwork. + returned: always + type: str + sample: eu-central + ip_range: + description: IP range of the subnetwork + returned: always + type: str + sample: 10.0.0.0/24 + gateway: + description: Gateway of this subnetwork + returned: always + type: str + sample: 10.0.0.1 + routes: + description: Routes belonging to the network + returned: always + type: complex + contains: + ip_range: + description: Destination network or host of this route. + returned: always + type: str + sample: 10.0.0.0/16 + gateway: + description: Gateway of this route + returned: always + type: str + sample: 10.0.0.1 + servers: + description: Servers attached to the network + returned: always + type: complex + contains: + id: + description: Numeric identifier of the server + returned: always + type: int + sample: 1937415 + name: + description: Name of the server + returned: always + type: str + sample: my-server + status: + description: Status of the server + returned: always + type: str + sample: running + server_type: + description: Name of the server type of the server + returned: always + type: str + sample: cx11 + ipv4_address: + description: Public IPv4 address of the server + returned: always + type: str + sample: 116.203.104.109 + ipv6: + description: IPv6 network of the server + returned: always + type: str + sample: 2a01:4f8:1c1c:c140::/64 + location: + description: Name of the location of the server + returned: always + type: str + sample: fsn1 + datacenter: + description: Name of the datacenter of the server + returned: always + type: str + sample: fsn1-dc14 + rescue_enabled: + description: True if rescue mode is enabled, Server will then boot into rescue system on next reboot + returned: always + type: bool + sample: false + backup_window: + description: Time window (UTC) in which the backup will run, or null if the backups are not enabled + returned: always + type: bool + sample: 22-02 + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict + delete_protection: + description: True if the network is protected for deletion + returned: always + type: bool + version_added: "0.1.0" + labels: + description: Labels of the network + returned: always + type: dict +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudNetworkInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_network_info") + self.hcloud_network_info = None + + def _prepare_result(self): + tmp = [] + + for network in self.hcloud_network_info: + if network is not None: + subnets = [] + for subnet in network.subnets: + prepared_subnet = { + "type": subnet.type, + "ip_range": subnet.ip_range, + "network_zone": subnet.network_zone, + "gateway": subnet.gateway, + } + subnets.append(prepared_subnet) + routes = [] + for route in network.routes: + prepared_route = { + "destination": route.destination, + "gateway": route.gateway + } + routes.append(prepared_route) + + servers = [] + for server in network.servers: + prepared_server = { + "id": to_native(server.id), + "name": to_native(server.name), + "ipv4_address": to_native(server.public_net.ipv4.ip), + "ipv6": to_native(server.public_net.ipv6.ip), + "image": to_native(server.image.name), + "server_type": to_native(server.server_type.name), + "datacenter": to_native(server.datacenter.name), + "location": to_native(server.datacenter.location.name), + "rescue_enabled": server.rescue_enabled, + "backup_window": to_native(server.backup_window), + "labels": server.labels, + "status": to_native(server.status), + } + servers.append(prepared_server) + + tmp.append({ + "id": to_native(network.id), + "name": to_native(network.name), + "ip_range": to_native(network.ip_range), + "subnetworks": subnets, + "routes": routes, + "servers": servers, + "labels": network.labels, + "delete_protection": network.protection["delete"], + }) + return tmp + + def get_networks(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_network_info = [self.client.networks.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_network_info = [self.client.networks.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_network_info = self.client.networks.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_network_info = self.client.networks.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudNetworkInfo.define_module() + + hcloud = AnsibleHcloudNetworkInfo(module) + hcloud.get_networks() + result = hcloud.get_result() + info = { + 'hcloud_network_info': result['hcloud_network_info'] + } + module.exit_json(**info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_rdns.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_rdns.py new file mode 100644 index 00000000..8bbfaedc --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_rdns.py @@ -0,0 +1,273 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_rdns + +short_description: Create and manage reverse DNS entries on the Hetzner Cloud. + + +description: + - Create, update and delete reverse DNS entries on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@lkaemmerling) + +options: + server: + description: + - The name of the Hetzner Cloud server you want to add the reverse DNS entry to. + type: str + floating_ip: + description: + - The name of the Hetzner Cloud Floating IP you want to add the reverse DNS entry to. + type: str + ip_address: + description: + - The IP address that should point to I(dns_ptr). + type: str + required: true + dns_ptr: + description: + - The DNS address the I(ip_address) should resolve to. + - Omit the param to reset the reverse DNS entry to the default value. + type: str + state: + description: + - State of the reverse DNS entry. + default: present + choices: [ absent, present ] + type: str + +requirements: + - hcloud-python >= 1.3.0 + +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a reverse DNS entry for a server + hcloud_rdns: + server: my-server + ip_address: 123.123.123.123 + dns_ptr: example.com + state: present + +- name: Create a reverse DNS entry for a Floating IP + hcloud_rdns: + floating_ip: my-floating-ip + ip_address: 123.123.123.123 + dns_ptr: example.com + state: present + +- name: Ensure the reverse DNS entry is absent (remove if needed) + hcloud_rdns: + server: my-server + ip_address: 123.123.123.123 + dns_ptr: example.com + state: absent +""" + +RETURN = """ +hcloud_rdns: + description: The reverse DNS entry + returned: always + type: complex + contains: + server: + description: Name of the server + type: str + returned: always + sample: my-server + floating_ip: + description: Name of the Floating IP + type: str + returned: always + sample: my-floating-ip + ip_address: + description: The IP address that point to the DNS ptr + type: str + returned: always + sample: 123.123.123.123 + dns_ptr: + description: The DNS that resolves to the IP + type: str + returned: always + sample: example.com +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudReverseDNS(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_rdns") + self.hcloud_resource = None + self.hcloud_rdns = None + + def _prepare_result(self): + result = { + "server": None, + "floating_ip": None, + "ip_address": to_native(self.hcloud_rdns["ip_address"]), + "dns_ptr": to_native(self.hcloud_rdns["dns_ptr"]), + } + + if self.module.params.get("server"): + result["server"] = to_native(self.hcloud_resource.name) + elif self.module.params.get("floating_ip"): + result["floating_ip"] = to_native(self.hcloud_resource.name) + return result + + def _get_resource(self): + try: + if self.module.params.get("server"): + self.hcloud_resource = self.client.servers.get_by_name( + self.module.params.get("server") + ) + elif self.module.params.get("floating_ip"): + self.hcloud_resource = self.client.floating_ips.get_by_name( + self.module.params.get("floating_ip") + ) + except APIException as e: + self.module.fail_json(msg=e.message) + + def _get_rdns(self): + ip_address = self.module.params.get("ip_address") + if utils.validate_ip_address(ip_address): + if self.module.params.get("server"): + if self.hcloud_resource.public_net.ipv4.ip == ip_address: + self.hcloud_rdns = { + "ip_address": self.hcloud_resource.public_net.ipv4.ip, + "dns_ptr": self.hcloud_resource.public_net.ipv4.dns_ptr, + } + else: + self.module.fail_json(msg="The selected server does not have this IP address") + elif self.module.params.get("floating_ip"): + if self.hcloud_resource.ip == ip_address: + self.hcloud_rdns = { + "ip_address": self.hcloud_resource.ip, + "dns_ptr": self.hcloud_resource.dns_ptr[0]["dns_ptr"], + } + else: + self.module.fail_json(msg="The selected Floating IP does not have this IP address") + + elif utils.validate_ip_v6_address(ip_address): + if self.module.params.get("server"): + for ipv6_address_dns_ptr in self.hcloud_resource.public_net.ipv6.dns_ptr: + if ipv6_address_dns_ptr["ip"] == ip_address: + self.hcloud_rdns = { + "ip_address": ipv6_address_dns_ptr["ip"], + "dns_ptr": ipv6_address_dns_ptr["dns_ptr"], + } + elif self.module.params.get("floating_ip"): + for ipv6_address_dns_ptr in self.hcloud_resource.dns_ptr: + if ipv6_address_dns_ptr["ip"] == ip_address: + self.hcloud_rdns = { + "ip_address": ipv6_address_dns_ptr["ip"], + "dns_ptr": ipv6_address_dns_ptr["dns_ptr"], + } + else: + self.module.fail_json(msg="The given IP address is not valid") + + def _create_rdns(self): + self.module.fail_on_missing_params( + required_params=["dns_ptr"] + ) + params = { + "ip": self.module.params.get("ip_address"), + "dns_ptr": self.module.params.get("dns_ptr"), + } + + if not self.module.check_mode: + self.hcloud_resource.change_dns_ptr(**params).wait_until_finished() + + self._mark_as_changed() + self._get_resource() + self._get_rdns() + + def _update_rdns(self): + dns_ptr = self.module.params.get("dns_ptr") + if dns_ptr != self.hcloud_rdns["dns_ptr"]: + params = { + "ip": self.module.params.get("ip_address"), + "dns_ptr": dns_ptr, + } + + if not self.module.check_mode: + self.hcloud_resource.change_dns_ptr(**params).wait_until_finished() + + self._mark_as_changed() + self._get_resource() + self._get_rdns() + + def present_rdns(self): + self._get_resource() + self._get_rdns() + if self.hcloud_rdns is None: + self._create_rdns() + else: + self._update_rdns() + + def delete_rdns(self): + self._get_resource() + self._get_rdns() + if self.hcloud_rdns is not None: + if not self.module.check_mode: + self.hcloud_resource.change_dns_ptr(ip=self.hcloud_rdns['ip_address'], dns_ptr=None) + self._mark_as_changed() + self.hcloud_rdns = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + server={"type": "str"}, + floating_ip={"type": "str"}, + ip_address={"type": "str", "required": True}, + dns_ptr={"type": "str"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + required_one_of=[['server', 'floating_ip']], + mutually_exclusive=[["server", "floating_ip"]], + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudReverseDNS.define_module() + + hcloud = AnsibleHcloudReverseDNS(module) + state = module.params["state"] + if state == "absent": + hcloud.delete_rdns() + elif state == "present": + hcloud.present_rdns() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_route.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_route.py new file mode 100644 index 00000000..fce3844e --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_route.py @@ -0,0 +1,195 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_route + +short_description: Create and delete cloud routes on the Hetzner Cloud. + + +description: + - Create, update and delete cloud routes on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@lkaemmerling) + +options: + network: + description: + - The name of the Hetzner Cloud Network. + type: str + required: true + destination: + description: + - Destination network or host of this route. + type: str + required: true + gateway: + description: + - Gateway for the route. + type: str + required: true + state: + description: + - State of the route. + default: present + choices: [ absent, present ] + type: str + +requirements: + - hcloud-python >= 1.3.0 + +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic route + hcloud_route: + network: my-network + destination: 10.100.1.0/24 + gateway: 10.0.1.1 + state: present + +- name: Ensure the route is absent + hcloud_route: + network: my-network + destination: 10.100.1.0/24 + gateway: 10.0.1.1 + state: absent +""" + +RETURN = """ +hcloud_route: + description: One Route of a Network + returned: always + type: complex + contains: + network: + description: Name of the Network + type: str + returned: always + sample: my-network + destination: + description: Destination network or host of this route + type: str + returned: always + sample: 10.0.0.0/8 + gateway: + description: Gateway of the route + type: str + returned: always + sample: 10.0.0.1 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException + from hcloud.networks.domain import NetworkRoute +except ImportError: + APIException = None + NetworkRoute = None + + +class AnsibleHcloudRoute(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_route") + self.hcloud_network = None + self.hcloud_route = None + + def _prepare_result(self): + return { + "network": to_native(self.hcloud_network.name), + "destination": to_native(self.hcloud_route.destination), + "gateway": self.hcloud_route.gateway, + } + + def _get_network(self): + try: + self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("network")) + self.hcloud_route = None + except APIException as e: + self.module.fail_json(msg=e.message) + + def _get_route(self): + destination = self.module.params.get("destination") + gateway = self.module.params.get("gateway") + for route in self.hcloud_network.routes: + if route.destination == destination and route.gateway == gateway: + self.hcloud_route = route + + def _create_route(self): + route = NetworkRoute( + destination=self.module.params.get("destination"), + gateway=self.module.params.get('gateway') + ) + + if not self.module.check_mode: + try: + self.hcloud_network.add_route(route=route).wait_until_finished() + except APIException as e: + self.module.fail_json(msg=e.message) + + self._mark_as_changed() + self._get_network() + self._get_route() + + def present_route(self): + self._get_network() + self._get_route() + if self.hcloud_route is None: + self._create_route() + + def delete_route(self): + self._get_network() + self._get_route() + if self.hcloud_route is not None and self.hcloud_network is not None: + if not self.module.check_mode: + self.hcloud_network.delete_route(self.hcloud_route).wait_until_finished() + self._mark_as_changed() + self.hcloud_route = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + network={"type": "str", "required": True}, + gateway={"type": "str", "required": True}, + destination={"type": "str", "required": True}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudRoute.define_module() + + hcloud = AnsibleHcloudRoute(module) + state = module.params["state"] + if state == "absent": + hcloud.delete_route() + elif state == "present": + hcloud.present_route() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server.py new file mode 100644 index 00000000..4cc48875 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server.py @@ -0,0 +1,564 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_server + +short_description: Create and manage cloud servers on the Hetzner Cloud. + + +description: + - Create, update and manage cloud servers on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the Hetzner Cloud server to manage. + - Only required if no server I(name) is given + type: int + name: + description: + - The Name of the Hetzner Cloud server to manage. + - Only required if no server I(id) is given or a server does not exists. + type: str + server_type: + description: + - The Server Type of the Hetzner Cloud server to manage. + - Required if server does not exists. + type: str + ssh_keys: + description: + - List of SSH key names + - The key names correspond to the SSH keys configured for your + Hetzner Cloud account access. + type: list + elements: str + volumes: + description: + - List of Volumes IDs that should be attached to the server on server creation. + type: list + elements: str + image: + description: + - Image the server should be created from. + - Required if server does not exists. + type: str + location: + description: + - Location of Server. + - Required if no I(datacenter) is given and server does not exists. + type: str + datacenter: + description: + - Datacenter of Server. + - Required of no I(location) is given and server does not exists. + type: str + backups: + description: + - Enable or disable Backups for the given Server. + type: bool + default: no + upgrade_disk: + description: + - Resize the disk size, when resizing a server. + - If you want to downgrade the server later, this value should be False. + type: bool + default: no + force_upgrade: + description: + - Force the upgrade of the server. + - Power off the server if it is running on upgrade. + type: bool + default: no + user_data: + description: + - User Data to be passed to the server on creation. + - Only used if server does not exists. + type: str + rescue_mode: + description: + - Add the Hetzner rescue system type you want the server to be booted into. + type: str + labels: + description: + - User-defined labels (key-value pairs). + type: dict + delete_protection: + description: + - Protect the Server for deletion. + - Needs to be the same as I(rebuild_protection). + type: bool + rebuild_protection: + description: + - Protect the Server for rebuild. + - Needs to be the same as I(delete_protection). + type: bool + state: + description: + - State of the server. + default: present + choices: [ absent, present, restarted, started, stopped, rebuild ] + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic server + hcloud_server: + name: my-server + server_type: cx11 + image: ubuntu-18.04 + state: present + +- name: Create a basic server with ssh key + hcloud_server: + name: my-server + server_type: cx11 + image: ubuntu-18.04 + location: fsn1 + ssh_keys: + - me@myorganisation + state: present + +- name: Resize an existing server + hcloud_server: + name: my-server + server_type: cx21 + upgrade_disk: yes + state: present + +- name: Ensure the server is absent (remove if needed) + hcloud_server: + name: my-server + state: absent + +- name: Ensure the server is started + hcloud_server: + name: my-server + state: started + +- name: Ensure the server is stopped + hcloud_server: + name: my-server + state: stopped + +- name: Ensure the server is restarted + hcloud_server: + name: my-server + state: restarted + +- name: Ensure the server is will be booted in rescue mode and therefore restarted + hcloud_server: + name: my-server + rescue_mode: linux64 + state: restarted + +- name: Ensure the server is rebuild + hcloud_server: + name: my-server + image: ubuntu-18.04 + state: rebuild +""" + +RETURN = """ +hcloud_server: + description: The server instance + returned: Always + type: complex + contains: + id: + description: Numeric identifier of the server + returned: always + type: int + sample: 1937415 + name: + description: Name of the server + returned: always + type: str + sample: my-server + status: + description: Status of the server + returned: always + type: str + sample: running + server_type: + description: Name of the server type of the server + returned: always + type: str + sample: cx11 + ipv4_address: + description: Public IPv4 address of the server + returned: always + type: str + sample: 116.203.104.109 + ipv6: + description: IPv6 network of the server + returned: always + type: str + sample: 2a01:4f8:1c1c:c140::/64 + location: + description: Name of the location of the server + returned: always + type: str + sample: fsn1 + datacenter: + description: Name of the datacenter of the server + returned: always + type: str + sample: fsn1-dc14 + rescue_enabled: + description: True if rescue mode is enabled, Server will then boot into rescue system on next reboot + returned: always + type: bool + sample: false + backup_window: + description: Time window (UTC) in which the backup will run, or null if the backups are not enabled + returned: always + type: bool + sample: 22-02 + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict + delete_protection: + description: True if server is protected for deletion + type: bool + returned: always + sample: false + version_added: "0.1.0" + rebuild_protection: + description: True if server is protected for rebuild + type: bool + returned: always + sample: false + version_added: "0.1.0" +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud.volumes.domain import Volume + from hcloud.ssh_keys.domain import SSHKey + from hcloud.servers.domain import Server + from hcloud import APIException +except ImportError: + APIException = None + Volume = None + SSHKey = None + Server = None + + +class AnsibleHcloudServer(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_server") + self.hcloud_server = None + + def _prepare_result(self): + image = None if self.hcloud_server.image is None else to_native(self.hcloud_server.image.name) + return { + "id": to_native(self.hcloud_server.id), + "name": to_native(self.hcloud_server.name), + "ipv4_address": to_native(self.hcloud_server.public_net.ipv4.ip), + "ipv6": to_native(self.hcloud_server.public_net.ipv6.ip), + "image": image, + "server_type": to_native(self.hcloud_server.server_type.name), + "datacenter": to_native(self.hcloud_server.datacenter.name), + "location": to_native(self.hcloud_server.datacenter.location.name), + "rescue_enabled": self.hcloud_server.rescue_enabled, + "backup_window": to_native(self.hcloud_server.backup_window), + "labels": self.hcloud_server.labels, + "delete_protection": self.hcloud_server.protection["delete"], + "rebuild_protection": self.hcloud_server.protection["rebuild"], + "status": to_native(self.hcloud_server.status), + } + + def _get_server(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_server = self.client.servers.get_by_id( + self.module.params.get("id") + ) + else: + self.hcloud_server = self.client.servers.get_by_name( + self.module.params.get("name") + ) + except APIException as e: + self.module.fail_json(msg=e.message) + + def _create_server(self): + + self.module.fail_on_missing_params( + required_params=["name", "server_type", "image"] + ) + + params = { + "name": self.module.params.get("name"), + "server_type": self.client.server_types.get_by_name( + self.module.params.get("server_type") + ), + "user_data": self.module.params.get("user_data"), + "labels": self.module.params.get("labels"), + } + if self.client.images.get_by_name(self.module.params.get("image")) is not None: + # When image name is not available look for id instead + params["image"] = self.client.images.get_by_name(self.module.params.get("image")) + else: + params["image"] = self.client.images.get_by_id(self.module.params.get("image")) + + if self.module.params.get("ssh_keys") is not None: + params["ssh_keys"] = [ + SSHKey(name=ssh_key_name) + for ssh_key_name in self.module.params.get("ssh_keys") + ] + + if self.module.params.get("volumes") is not None: + params["volumes"] = [ + Volume(id=volume_id) for volume_id in self.module.params.get("volumes") + ] + + if self.module.params.get("location") is None and self.module.params.get("datacenter") is None: + # When not given, the API will choose the location. + params["location"] = None + params["datacenter"] = None + elif self.module.params.get("location") is not None and self.module.params.get("datacenter") is None: + params["location"] = self.client.locations.get_by_name( + self.module.params.get("location") + ) + elif self.module.params.get("location") is None and self.module.params.get("datacenter") is not None: + params["datacenter"] = self.client.datacenters.get_by_name( + self.module.params.get("datacenter") + ) + + if not self.module.check_mode: + resp = self.client.servers.create(**params) + self.result["root_password"] = resp.root_password + resp.action.wait_until_finished(max_retries=1000) + [action.wait_until_finished() for action in resp.next_actions] + + rescue_mode = self.module.params.get("rescue_mode") + if rescue_mode: + self._get_server() + self._set_rescue_mode(rescue_mode) + + backups = self.module.params.get("backups") + if backups: + self._get_server() + self.hcloud_server.enable_backup().wait_until_finished() + + delete_protection = self.module.params.get("delete_protection") + rebuild_protection = self.module.params.get("rebuild_protection") + if delete_protection is not None and rebuild_protection is not None: + self._get_server() + self.hcloud_server.change_protection(delete=delete_protection, + rebuild=rebuild_protection).wait_until_finished() + self._mark_as_changed() + self._get_server() + + def _update_server(self): + try: + rescue_mode = self.module.params.get("rescue_mode") + if rescue_mode and self.hcloud_server.rescue_enabled is False: + if not self.module.check_mode: + self._set_rescue_mode(rescue_mode) + self._mark_as_changed() + elif not rescue_mode and self.hcloud_server.rescue_enabled is True: + if not self.module.check_mode: + self.hcloud_server.disable_rescue().wait_until_finished() + self._mark_as_changed() + + if self.module.params.get("backups") and self.hcloud_server.backup_window is None: + if not self.module.check_mode: + self.hcloud_server.enable_backup().wait_until_finished() + self._mark_as_changed() + elif not self.module.params.get("backups") and self.hcloud_server.backup_window is not None: + if not self.module.check_mode: + self.hcloud_server.disable_backup().wait_until_finished() + self._mark_as_changed() + + labels = self.module.params.get("labels") + if labels is not None and labels != self.hcloud_server.labels: + if not self.module.check_mode: + self.hcloud_server.update(labels=labels) + self._mark_as_changed() + + server_type = self.module.params.get("server_type") + if server_type is not None and self.hcloud_server.server_type.name != server_type: + previous_server_status = self.hcloud_server.status + state = self.module.params.get("state") + if previous_server_status == Server.STATUS_RUNNING: + if not self.module.check_mode: + if self.module.params.get("force_upgrade") or state == "stopped": + self.stop_server() # Only stopped server can be upgraded + else: + self.module.warn( + "You can not upgrade a running instance %s. You need to stop the instance or use force_upgrade=yes." + % self.hcloud_server.name + ) + timeout = 100 + if self.module.params.get("upgrade_disk"): + timeout = ( + 1000 + ) # When we upgrade the disk too the resize progress takes some more time. + if not self.module.check_mode: + self.hcloud_server.change_type( + server_type=self.client.server_types.get_by_name(server_type), + upgrade_disk=self.module.params.get("upgrade_disk"), + ).wait_until_finished(timeout) + if state == "present" and previous_server_status == Server.STATUS_RUNNING or state == "started": + self.start_server() + + self._mark_as_changed() + + delete_protection = self.module.params.get("delete_protection") + rebuild_protection = self.module.params.get("rebuild_protection") + if (delete_protection is not None and rebuild_protection is not None) and ( + delete_protection != self.hcloud_server.protection["delete"] or rebuild_protection != + self.hcloud_server.protection["rebuild"]): + if not self.module.check_mode: + self.hcloud_server.change_protection(delete=delete_protection, + rebuild=rebuild_protection).wait_until_finished() + self._mark_as_changed() + self._get_server() + except APIException as e: + self.module.fail_json(msg=e.message) + + def _set_rescue_mode(self, rescue_mode): + if self.module.params.get("ssh_keys"): + resp = self.hcloud_server.enable_rescue(type=rescue_mode, + ssh_keys=[self.client.ssh_keys.get_by_name(ssh_key_name).id + for + ssh_key_name in + self.module.params.get("ssh_keys")]) + else: + resp = self.hcloud_server.enable_rescue(type=rescue_mode) + resp.action.wait_until_finished() + self.result["root_password"] = resp.root_password + + def start_server(self): + try: + if self.hcloud_server.status != Server.STATUS_RUNNING: + if not self.module.check_mode: + self.client.servers.power_on(self.hcloud_server).wait_until_finished() + self._mark_as_changed() + self._get_server() + except APIException as e: + self.module.fail_json(msg=e.message) + + def stop_server(self): + try: + if self.hcloud_server.status != Server.STATUS_OFF: + if not self.module.check_mode: + self.client.servers.power_off(self.hcloud_server).wait_until_finished() + self._mark_as_changed() + self._get_server() + except APIException as e: + self.module.fail_json(msg=e.message) + + def rebuild_server(self): + self.module.fail_on_missing_params( + required_params=["image"] + ) + try: + if not self.module.check_mode: + self.client.servers.rebuild(self.hcloud_server, self.client.images.get_by_name( + self.module.params.get("image"))).wait_until_finished() + self._mark_as_changed() + + self._get_server() + except APIException as e: + self.module.fail_json(msg=e.message) + + def present_server(self): + self._get_server() + if self.hcloud_server is None: + self._create_server() + else: + self._update_server() + + def delete_server(self): + try: + self._get_server() + if self.hcloud_server is not None: + if not self.module.check_mode: + self.client.servers.delete(self.hcloud_server).wait_until_finished() + self._mark_as_changed() + self.hcloud_server = None + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + image={"type": "str"}, + server_type={"type": "str"}, + location={"type": "str"}, + datacenter={"type": "str"}, + user_data={"type": "str"}, + ssh_keys={"type": "list", "elements": "str"}, + volumes={"type": "list", "elements": "str"}, + labels={"type": "dict"}, + backups={"type": "bool", "default": False}, + upgrade_disk={"type": "bool", "default": False}, + force_upgrade={"type": "bool", "default": False}, + rescue_mode={"type": "str"}, + delete_protection={"type": "bool"}, + rebuild_protection={"type": "bool"}, + state={ + "choices": ["absent", "present", "restarted", "started", "stopped", "rebuild"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + required_one_of=[['id', 'name']], + mutually_exclusive=[["location", "datacenter"]], + required_together=[["delete_protection", "rebuild_protection"]], + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudServer.define_module() + + hcloud = AnsibleHcloudServer(module) + state = module.params.get("state") + if state == "absent": + hcloud.delete_server() + elif state == "present": + hcloud.present_server() + elif state == "started": + hcloud.present_server() + hcloud.start_server() + elif state == "stopped": + hcloud.present_server() + hcloud.stop_server() + elif state == "restarted": + hcloud.present_server() + hcloud.stop_server() + hcloud.start_server() + elif state == "rebuild": + hcloud.present_server() + hcloud.rebuild_server() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_facts.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_facts.py new file mode 100644 index 00000000..f99d1c8c --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_facts.py @@ -0,0 +1,224 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_server_info + +short_description: Gather infos about your Hetzner Cloud servers. + + +description: + - Gather infos about your Hetzner Cloud servers. + - This module was called C(hcloud_server_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_server_facts). + Note that the M(hetzner.hcloud.hcloud_server_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_server_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the server you want to get. + type: int + name: + description: + - The name of the server you want to get. + type: str + label_selector: + description: + - The label selector for the server you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud server infos + hcloud_server_info: + register: output + +- name: Print the gathered infos + debug: + var: output.hcloud_server_info +""" + +RETURN = """ +hcloud_server_info: + description: The server infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the server + returned: always + type: int + sample: 1937415 + name: + description: Name of the server + returned: always + type: str + sample: my-server + status: + description: Status of the server + returned: always + type: str + sample: running + server_type: + description: Name of the server type of the server + returned: always + type: str + sample: cx11 + ipv4_address: + description: Public IPv4 address of the server + returned: always + type: str + sample: 116.203.104.109 + ipv6: + description: IPv6 network of the server + returned: always + type: str + sample: 2a01:4f8:1c1c:c140::/64 + location: + description: Name of the location of the server + returned: always + type: str + sample: fsn1 + datacenter: + description: Name of the datacenter of the server + returned: always + type: str + sample: fsn1-dc14 + rescue_enabled: + description: True if rescue mode is enabled, Server will then boot into rescue system on next reboot + returned: always + type: bool + sample: false + backup_window: + description: Time window (UTC) in which the backup will run, or null if the backups are not enabled + returned: always + type: bool + sample: 22-02 + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict + delete_protection: + description: True if server is protected for deletion + type: bool + returned: always + sample: false + version_added: "0.1.0" + rebuild_protection: + description: True if server is protected for rebuild + type: bool + returned: always + sample: false + version_added: "0.1.0" +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudServerInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_server_info") + self.hcloud_server_info = None + + def _prepare_result(self): + tmp = [] + + for server in self.hcloud_server_info: + if server is not None: + image = None if server.image is None else to_native(server.image.name) + tmp.append({ + "id": to_native(server.id), + "name": to_native(server.name), + "ipv4_address": to_native(server.public_net.ipv4.ip), + "ipv6": to_native(server.public_net.ipv6.ip), + "image": image, + "server_type": to_native(server.server_type.name), + "datacenter": to_native(server.datacenter.name), + "location": to_native(server.datacenter.location.name), + "rescue_enabled": server.rescue_enabled, + "backup_window": to_native(server.backup_window), + "labels": server.labels, + "status": to_native(server.status), + "delete_protection": server.protection["delete"], + "rebuild_protection": server.protection["rebuild"], + }) + return tmp + + def get_servers(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_server_info = [self.client.servers.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_server_info = [self.client.servers.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_server_info = self.client.servers.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_server_info = self.client.servers.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudServerInfo.define_module() + + is_old_facts = module._name == 'hcloud_server_facts' + if is_old_facts: + module.deprecate("The 'hcloud_server_facts' module has been renamed to 'hcloud_server_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudServerInfo(module) + hcloud.get_servers() + result = hcloud.get_result() + + if is_old_facts: + ansible_info = { + 'hcloud_server_facts': result['hcloud_server_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_server_info': result['hcloud_server_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_info.py new file mode 100644 index 00000000..f99d1c8c --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_info.py @@ -0,0 +1,224 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_server_info + +short_description: Gather infos about your Hetzner Cloud servers. + + +description: + - Gather infos about your Hetzner Cloud servers. + - This module was called C(hcloud_server_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_server_facts). + Note that the M(hetzner.hcloud.hcloud_server_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_server_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the server you want to get. + type: int + name: + description: + - The name of the server you want to get. + type: str + label_selector: + description: + - The label selector for the server you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud server infos + hcloud_server_info: + register: output + +- name: Print the gathered infos + debug: + var: output.hcloud_server_info +""" + +RETURN = """ +hcloud_server_info: + description: The server infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the server + returned: always + type: int + sample: 1937415 + name: + description: Name of the server + returned: always + type: str + sample: my-server + status: + description: Status of the server + returned: always + type: str + sample: running + server_type: + description: Name of the server type of the server + returned: always + type: str + sample: cx11 + ipv4_address: + description: Public IPv4 address of the server + returned: always + type: str + sample: 116.203.104.109 + ipv6: + description: IPv6 network of the server + returned: always + type: str + sample: 2a01:4f8:1c1c:c140::/64 + location: + description: Name of the location of the server + returned: always + type: str + sample: fsn1 + datacenter: + description: Name of the datacenter of the server + returned: always + type: str + sample: fsn1-dc14 + rescue_enabled: + description: True if rescue mode is enabled, Server will then boot into rescue system on next reboot + returned: always + type: bool + sample: false + backup_window: + description: Time window (UTC) in which the backup will run, or null if the backups are not enabled + returned: always + type: bool + sample: 22-02 + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict + delete_protection: + description: True if server is protected for deletion + type: bool + returned: always + sample: false + version_added: "0.1.0" + rebuild_protection: + description: True if server is protected for rebuild + type: bool + returned: always + sample: false + version_added: "0.1.0" +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudServerInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_server_info") + self.hcloud_server_info = None + + def _prepare_result(self): + tmp = [] + + for server in self.hcloud_server_info: + if server is not None: + image = None if server.image is None else to_native(server.image.name) + tmp.append({ + "id": to_native(server.id), + "name": to_native(server.name), + "ipv4_address": to_native(server.public_net.ipv4.ip), + "ipv6": to_native(server.public_net.ipv6.ip), + "image": image, + "server_type": to_native(server.server_type.name), + "datacenter": to_native(server.datacenter.name), + "location": to_native(server.datacenter.location.name), + "rescue_enabled": server.rescue_enabled, + "backup_window": to_native(server.backup_window), + "labels": server.labels, + "status": to_native(server.status), + "delete_protection": server.protection["delete"], + "rebuild_protection": server.protection["rebuild"], + }) + return tmp + + def get_servers(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_server_info = [self.client.servers.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_server_info = [self.client.servers.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_server_info = self.client.servers.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_server_info = self.client.servers.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudServerInfo.define_module() + + is_old_facts = module._name == 'hcloud_server_facts' + if is_old_facts: + module.deprecate("The 'hcloud_server_facts' module has been renamed to 'hcloud_server_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudServerInfo(module) + hcloud.get_servers() + result = hcloud.get_result() + + if is_old_facts: + ansible_info = { + 'hcloud_server_facts': result['hcloud_server_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_server_info': result['hcloud_server_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_network.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_network.py new file mode 100644 index 00000000..285b2fe3 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_network.py @@ -0,0 +1,243 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_server_network + +short_description: Manage the relationship between Hetzner Cloud Networks and servers + + +description: + - Create and delete the relationship Hetzner Cloud Networks and servers + +author: + - Lukas Kaemmerling (@lkaemmerling) + +options: + network: + description: + - The name of the Hetzner Cloud Networks. + type: str + required: true + server: + description: + - The name of the Hetzner Cloud server. + type: str + required: true + ip: + description: + - The IP the server should have. + type: str + alias_ips: + description: + - Alias IPs the server has. + type: list + elements: str + state: + description: + - State of the server_network. + default: present + choices: [ absent, present ] + type: str + +requirements: + - hcloud-python >= 1.3.0 + +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic server network + hcloud_server_network: + network: my-network + server: my-server + state: present + +- name: Create a server network and specify the ip address + hcloud_server_network: + network: my-network + server: my-server + ip: 10.0.0.1 + state: present + +- name: Create a server network and add alias ips + hcloud_server_network: + network: my-network + server: my-server + ip: 10.0.0.1 + alias_ips: + - 10.1.0.1 + - 10.2.0.1 + state: present + +- name: Ensure the server network is absent (remove if needed) + hcloud_server_network: + network: my-network + server: my-server + state: absent +""" + +RETURN = """ +hcloud_server_network: + description: The relationship between a server and a network + returned: always + type: complex + contains: + network: + description: Name of the Network + type: str + returned: always + sample: my-network + server: + description: Name of the server + type: str + returned: always + sample: my-server + ip: + description: IP of the server within the Network ip range + type: str + returned: always + sample: 10.0.0.8 + alias_ips: + description: Alias IPs of the server within the Network ip range + type: str + returned: always + sample: [10.1.0.1, ...] +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudServerNetwork(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_server_network") + self.hcloud_network = None + self.hcloud_server = None + self.hcloud_server_network = None + + def _prepare_result(self): + return { + "network": to_native(self.hcloud_network.name), + "server": to_native(self.hcloud_server.name), + "ip": to_native(self.hcloud_server_network.ip), + "alias_ips": self.hcloud_server_network.alias_ips, + } + + def _get_server_and_network(self): + try: + self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("network")) + self.hcloud_server = self.client.servers.get_by_name(self.module.params.get("server")) + self.hcloud_server_network = None + except APIException as e: + self.module.fail_json(msg=e.message) + + def _get_server_network(self): + for privateNet in self.hcloud_server.private_net: + if privateNet.network.id == self.hcloud_network.id: + self.hcloud_server_network = privateNet + + def _create_server_network(self): + params = { + "network": self.hcloud_network + } + + if self.module.params.get("ip") is not None: + params["ip"] = self.module.params.get("ip") + if self.module.params.get("alias_ips") is not None: + params["alias_ips"] = self.module.params.get("alias_ips") + + if not self.module.check_mode: + try: + self.hcloud_server.attach_to_network(**params).wait_until_finished() + except APIException as e: + self.module.fail_json(msg=e.message) + + self._mark_as_changed() + self._get_server_and_network() + self._get_server_network() + + def _update_server_network(self): + params = { + "network": self.hcloud_network + } + alias_ips = self.module.params.get("alias_ips") + if alias_ips is not None and self.hcloud_server_network.alias_ips.sort() != alias_ips.sort(): + params["alias_ips"] = alias_ips + + if not self.module.check_mode: + try: + self.hcloud_server.change_alias_ips(**params).wait_until_finished() + except APIException as e: + self.module.fail_json(msg=e.message) + + self._mark_as_changed() + self._get_server_and_network() + self._get_server_network() + + def present_server_network(self): + self._get_server_and_network() + self._get_server_network() + if self.hcloud_server_network is None: + self._create_server_network() + else: + self._update_server_network() + + def delete_server_network(self): + self._get_server_and_network() + self._get_server_network() + if self.hcloud_server_network is not None and self.hcloud_server is not None: + if not self.module.check_mode: + self.hcloud_server.detach_from_network(self.hcloud_server_network.network).wait_until_finished() + self._mark_as_changed() + self.hcloud_server_network = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + network={"type": "str", "required": True}, + server={"type": "str", "required": True}, + ip={"type": "str"}, + alias_ips={"type": "list", "elements": "str"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudServerNetwork.define_module() + + hcloud = AnsibleHcloudServerNetwork(module) + state = module.params["state"] + if state == "absent": + hcloud.delete_server_network() + elif state == "present": + hcloud.present_server_network() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_facts.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_facts.py new file mode 100644 index 00000000..5b575d93 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_facts.py @@ -0,0 +1,182 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_server_type_info + +short_description: Gather infos about the Hetzner Cloud server types. + + +description: + - Gather infos about your Hetzner Cloud server types. + - This module was called C(hcloud_server_type_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_server_type_facts). + Note that the M(hetzner.hcloud.hcloud_server_type_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_server_type_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the server type you want to get. + type: int + name: + description: + - The name of the server type you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud server type infos + hcloud_server_type_info: + register: output + +- name: Print the gathered infos + debug: + var: output.hcloud_server_type_info +""" + +RETURN = """ +hcloud_server_type_info: + description: The server type infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the server type + returned: always + type: int + sample: 1937415 + name: + description: Name of the server type + returned: always + type: str + sample: fsn1 + description: + description: Detail description of the server type + returned: always + type: str + sample: Falkenstein DC Park 1 + cores: + description: Number of cpu cores a server of this type will have + returned: always + type: int + sample: 1 + memory: + description: Memory a server of this type will have in GB + returned: always + type: int + sample: 1 + disk: + description: Disk size a server of this type will have in GB + returned: always + type: int + sample: 25 + storage_type: + description: Type of server boot drive + returned: always + type: str + sample: local + cpu_type: + description: Type of cpu + returned: always + type: str + sample: shared +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudServerTypeInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_server_type_info") + self.hcloud_server_type_info = None + + def _prepare_result(self): + tmp = [] + + for server_type in self.hcloud_server_type_info: + if server_type is not None: + tmp.append({ + "id": to_native(server_type.id), + "name": to_native(server_type.name), + "description": to_native(server_type.description), + "cores": server_type.cores, + "memory": server_type.memory, + "disk": server_type.disk, + "storage_type": to_native(server_type.storage_type), + "cpu_type": to_native(server_type.cpu_type) + }) + return tmp + + def get_server_types(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_server_type_info = [self.client.server_types.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_server_type_info = [self.client.server_types.get_by_name( + self.module.params.get("name") + )] + else: + self.hcloud_server_type_info = self.client.server_types.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudServerTypeInfo.define_module() + + is_old_facts = module._name == 'hcloud_server_type_facts' + if is_old_facts: + module.deprecate("The 'hcloud_server_type_info' module has been renamed to 'hcloud_server_type_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudServerTypeInfo(module) + hcloud.get_server_types() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_server_type_info': result['hcloud_server_type_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_server_type_info': result['hcloud_server_type_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_info.py new file mode 100644 index 00000000..5b575d93 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_server_type_info.py @@ -0,0 +1,182 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_server_type_info + +short_description: Gather infos about the Hetzner Cloud server types. + + +description: + - Gather infos about your Hetzner Cloud server types. + - This module was called C(hcloud_server_type_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_server_type_facts). + Note that the M(hetzner.hcloud.hcloud_server_type_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_server_type_info)! + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the server type you want to get. + type: int + name: + description: + - The name of the server type you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud server type infos + hcloud_server_type_info: + register: output + +- name: Print the gathered infos + debug: + var: output.hcloud_server_type_info +""" + +RETURN = """ +hcloud_server_type_info: + description: The server type infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the server type + returned: always + type: int + sample: 1937415 + name: + description: Name of the server type + returned: always + type: str + sample: fsn1 + description: + description: Detail description of the server type + returned: always + type: str + sample: Falkenstein DC Park 1 + cores: + description: Number of cpu cores a server of this type will have + returned: always + type: int + sample: 1 + memory: + description: Memory a server of this type will have in GB + returned: always + type: int + sample: 1 + disk: + description: Disk size a server of this type will have in GB + returned: always + type: int + sample: 25 + storage_type: + description: Type of server boot drive + returned: always + type: str + sample: local + cpu_type: + description: Type of cpu + returned: always + type: str + sample: shared +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudServerTypeInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_server_type_info") + self.hcloud_server_type_info = None + + def _prepare_result(self): + tmp = [] + + for server_type in self.hcloud_server_type_info: + if server_type is not None: + tmp.append({ + "id": to_native(server_type.id), + "name": to_native(server_type.name), + "description": to_native(server_type.description), + "cores": server_type.cores, + "memory": server_type.memory, + "disk": server_type.disk, + "storage_type": to_native(server_type.storage_type), + "cpu_type": to_native(server_type.cpu_type) + }) + return tmp + + def get_server_types(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_server_type_info = [self.client.server_types.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_server_type_info = [self.client.server_types.get_by_name( + self.module.params.get("name") + )] + else: + self.hcloud_server_type_info = self.client.server_types.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudServerTypeInfo.define_module() + + is_old_facts = module._name == 'hcloud_server_type_facts' + if is_old_facts: + module.deprecate("The 'hcloud_server_type_info' module has been renamed to 'hcloud_server_type_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudServerTypeInfo(module) + hcloud.get_server_types() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_server_type_info': result['hcloud_server_type_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_server_type_info': result['hcloud_server_type_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key.py new file mode 100644 index 00000000..31c9625e --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key.py @@ -0,0 +1,245 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_ssh_key + +short_description: Create and manage ssh keys on the Hetzner Cloud. + + +description: + - Create, update and manage ssh keys on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the Hetzner Cloud ssh_key to manage. + - Only required if no ssh_key I(name) is given + type: int + name: + description: + - The Name of the Hetzner Cloud ssh_key to manage. + - Only required if no ssh_key I(id) is given or a ssh_key does not exists. + type: str + fingerprint: + description: + - The Fingerprint of the Hetzner Cloud ssh_key to manage. + - Only required if no ssh_key I(id) or I(name) is given. + type: str + labels: + description: + - User-defined labels (key-value pairs) + type: dict + public_key: + description: + - The Public Key to add. + - Required if ssh_key does not exists. + type: str + state: + description: + - State of the ssh_key. + default: present + choices: [ absent, present ] + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic ssh_key + hcloud_ssh_key: + name: my-ssh_key + public_key: "ssh-rsa AAAjjk76kgf...Xt" + state: present + +- name: Create a ssh_key with labels + hcloud_ssh_key: + name: my-ssh_key + public_key: "ssh-rsa AAAjjk76kgf...Xt" + labels: + key: value + mylabel: 123 + state: present + +- name: Ensure the ssh_key is absent (remove if needed) + hcloud_ssh_key: + name: my-ssh_key + state: absent +""" + +RETURN = """ +hcloud_ssh_key: + description: The ssh_key instance + returned: Always + type: complex + contains: + id: + description: ID of the ssh_key + type: int + returned: Always + sample: 12345 + name: + description: Name of the ssh_key + type: str + returned: Always + sample: my-ssh-key + fingerprint: + description: Fingerprint of the ssh_key + type: str + returned: Always + sample: b7:2f:30:a0:2f:6c:58:6c:21:04:58:61:ba:06:3b:2f + public_key: + description: Public key of the ssh_key + type: str + returned: Always + sample: "ssh-rsa AAAjjk76kgf...Xt" + labels: + description: User-defined labels (key-value pairs) + type: dict + returned: Always + sample: + key: value + mylabel: 123 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud.volumes.domain import Volume + from hcloud.ssh_keys.domain import SSHKey + from hcloud.ssh_keys.domain import Server + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudSSHKey(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_ssh_key") + self.hcloud_ssh_key = None + + def _prepare_result(self): + return { + "id": to_native(self.hcloud_ssh_key.id), + "name": to_native(self.hcloud_ssh_key.name), + "fingerprint": to_native(self.hcloud_ssh_key.fingerprint), + "public_key": to_native(self.hcloud_ssh_key.public_key), + "labels": self.hcloud_ssh_key.labels, + } + + def _get_ssh_key(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_ssh_key = self.client.ssh_keys.get_by_id( + self.module.params.get("id") + ) + elif self.module.params.get("fingerprint") is not None: + self.hcloud_ssh_key = self.client.ssh_keys.get_by_fingerprint( + self.module.params.get("fingerprint") + ) + elif self.module.params.get("name") is not None: + self.hcloud_ssh_key = self.client.ssh_keys.get_by_name( + self.module.params.get("name") + ) + + except APIException as e: + self.module.fail_json(msg=e.message) + + def _create_ssh_key(self): + self.module.fail_on_missing_params( + required_params=["name", "public_key"] + ) + params = { + "name": self.module.params.get("name"), + "public_key": self.module.params.get("public_key"), + "labels": self.module.params.get("labels") + } + + if not self.module.check_mode: + self.client.ssh_keys.create(**params) + self._mark_as_changed() + self._get_ssh_key() + + def _update_ssh_key(self): + name = self.module.params.get("name") + if name is not None and self.hcloud_ssh_key.name != name: + self.module.fail_on_missing_params( + required_params=["id"] + ) + if not self.module.check_mode: + self.hcloud_ssh_key.update(name=name) + self._mark_as_changed() + + labels = self.module.params.get("labels") + if labels is not None and self.hcloud_ssh_key.labels != labels: + if not self.module.check_mode: + self.hcloud_ssh_key.update(labels=labels) + self._mark_as_changed() + + self._get_ssh_key() + + def present_ssh_key(self): + self._get_ssh_key() + if self.hcloud_ssh_key is None: + self._create_ssh_key() + else: + self._update_ssh_key() + + def delete_ssh_key(self): + self._get_ssh_key() + if self.hcloud_ssh_key is not None: + if not self.module.check_mode: + self.client.ssh_keys.delete(self.hcloud_ssh_key) + self._mark_as_changed() + self.hcloud_ssh_key = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + public_key={"type": "str"}, + fingerprint={"type": "str"}, + labels={"type": "dict"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + required_one_of=[['id', 'name', 'fingerprint']], + required_if=[['state', 'present', ['name']]], + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudSSHKey.define_module() + + hcloud = AnsibleHcloudSSHKey(module) + state = module.params.get("state") + if state == "absent": + hcloud.delete_ssh_key() + elif state == "present": + hcloud.present_ssh_key() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_facts.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_facts.py new file mode 100644 index 00000000..ad2b4fda --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_facts.py @@ -0,0 +1,174 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_ssh_key_info +short_description: Gather infos about your Hetzner Cloud ssh_keys. +description: + - Gather facts about your Hetzner Cloud ssh_keys. + - This module was called C(hcloud_ssh_key_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_ssh_key_facts). + Note that the M(hetzner.hcloud.hcloud_ssh_key_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_ssh_key_info)! +author: + - Christopher Schmitt (@cschmitt-hcloud) +options: + id: + description: + - The ID of the ssh key you want to get. + type: int + name: + description: + - The name of the ssh key you want to get. + type: str + fingerprint: + description: + - The fingerprint of the ssh key you want to get. + type: str + label_selector: + description: + - The label selector for the ssh key you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud sshkey infos + hcloud_ssh_key_info: + register: output +- name: Print the gathered infos + debug: + var: output.hcloud_ssh_key_info +""" + +RETURN = """ +hcloud_ssh_key_info: + description: The ssh key instances + returned: Always + type: complex + contains: + id: + description: Numeric identifier of the ssh_key + returned: always + type: int + sample: 1937415 + name: + description: Name of the ssh_key + returned: always + type: str + sample: my-ssh-key + fingerprint: + description: Fingerprint of the ssh key + returned: always + type: str + sample: 0e:e0:bd:c7:2d:1f:69:49:94:44:91:f1:19:fd:35:f3 + public_key: + description: The actual public key + returned: always + type: str + sample: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpl/tnk74nnQJxxLAtutUApUZMRJxryKh7VXkNbd4g9 john@example.com" + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudSSHKeyInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_ssh_key_info") + self.hcloud_ssh_key_info = None + + def _prepare_result(self): + ssh_keys = [] + + for ssh_key in self.hcloud_ssh_key_info: + if ssh_key: + ssh_keys.append({ + "id": to_native(ssh_key.id), + "name": to_native(ssh_key.name), + "fingerprint": to_native(ssh_key.fingerprint), + "public_key": to_native(ssh_key.public_key), + "labels": ssh_key.labels + }) + return ssh_keys + + def get_ssh_keys(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("fingerprint") is not None: + self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_fingerprint( + self.module.params.get("fingerprint") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_ssh_key_info = self.client.ssh_keys.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_ssh_key_info = self.client.ssh_keys.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + fingerprint={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudSSHKeyInfo.define_module() + + is_old_facts = module._name == 'hcloud_ssh_key_facts' + if is_old_facts: + module.deprecate("The 'hcloud_ssh_key_facts' module has been renamed to 'hcloud_ssh_key_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudSSHKeyInfo(module) + hcloud.get_ssh_keys() + result = hcloud.get_result() + + if is_old_facts: + ansible_info = { + 'hcloud_ssh_key_facts': result['hcloud_ssh_key_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_ssh_key_info': result['hcloud_ssh_key_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_info.py new file mode 100644 index 00000000..ad2b4fda --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_ssh_key_info.py @@ -0,0 +1,174 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_ssh_key_info +short_description: Gather infos about your Hetzner Cloud ssh_keys. +description: + - Gather facts about your Hetzner Cloud ssh_keys. + - This module was called C(hcloud_ssh_key_facts) before Ansible 2.9, returning C(ansible_facts) and C(hcloud_ssh_key_facts). + Note that the M(hetzner.hcloud.hcloud_ssh_key_info) module no longer returns C(ansible_facts) and the value was renamed to C(hcloud_ssh_key_info)! +author: + - Christopher Schmitt (@cschmitt-hcloud) +options: + id: + description: + - The ID of the ssh key you want to get. + type: int + name: + description: + - The name of the ssh key you want to get. + type: str + fingerprint: + description: + - The fingerprint of the ssh key you want to get. + type: str + label_selector: + description: + - The label selector for the ssh key you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud sshkey infos + hcloud_ssh_key_info: + register: output +- name: Print the gathered infos + debug: + var: output.hcloud_ssh_key_info +""" + +RETURN = """ +hcloud_ssh_key_info: + description: The ssh key instances + returned: Always + type: complex + contains: + id: + description: Numeric identifier of the ssh_key + returned: always + type: int + sample: 1937415 + name: + description: Name of the ssh_key + returned: always + type: str + sample: my-ssh-key + fingerprint: + description: Fingerprint of the ssh key + returned: always + type: str + sample: 0e:e0:bd:c7:2d:1f:69:49:94:44:91:f1:19:fd:35:f3 + public_key: + description: The actual public key + returned: always + type: str + sample: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpl/tnk74nnQJxxLAtutUApUZMRJxryKh7VXkNbd4g9 john@example.com" + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudSSHKeyInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_ssh_key_info") + self.hcloud_ssh_key_info = None + + def _prepare_result(self): + ssh_keys = [] + + for ssh_key in self.hcloud_ssh_key_info: + if ssh_key: + ssh_keys.append({ + "id": to_native(ssh_key.id), + "name": to_native(ssh_key.name), + "fingerprint": to_native(ssh_key.fingerprint), + "public_key": to_native(ssh_key.public_key), + "labels": ssh_key.labels + }) + return ssh_keys + + def get_ssh_keys(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("fingerprint") is not None: + self.hcloud_ssh_key_info = [self.client.ssh_keys.get_by_fingerprint( + self.module.params.get("fingerprint") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_ssh_key_info = self.client.ssh_keys.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_ssh_key_info = self.client.ssh_keys.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + fingerprint={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudSSHKeyInfo.define_module() + + is_old_facts = module._name == 'hcloud_ssh_key_facts' + if is_old_facts: + module.deprecate("The 'hcloud_ssh_key_facts' module has been renamed to 'hcloud_ssh_key_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudSSHKeyInfo(module) + hcloud.get_ssh_keys() + result = hcloud.get_result() + + if is_old_facts: + ansible_info = { + 'hcloud_ssh_key_facts': result['hcloud_ssh_key_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_ssh_key_info': result['hcloud_ssh_key_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_subnetwork.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_subnetwork.py new file mode 100644 index 00000000..fd199804 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_subnetwork.py @@ -0,0 +1,246 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_subnetwork + +short_description: Manage cloud subnetworks on the Hetzner Cloud. + + +description: + - Create, update and delete cloud subnetworks on the Hetzner Cloud. + +author: + - Lukas Kaemmerling (@lkaemmerling) + +options: + network: + description: + - The ID or Name of the Hetzner Cloud Networks. + type: str + required: true + ip_range: + description: + - IP range of the subnetwork. + type: str + required: true + type: + description: + - Type of subnetwork. + type: str + choices: [ server, cloud, vswitch ] + required: true + network_zone: + description: + - Name of network zone. + type: str + required: true + vswitch_id: + description: + - ID of the vSwitch you want to couple with your Network. + - Required if type == vswitch + type: int + state: + description: + - State of the subnetwork. + default: present + choices: [ absent, present ] + type: str + +requirements: + - hcloud-python >= 1.10.0 + +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a basic subnetwork + hcloud_subnetwork: + network: my-network + ip_range: 10.0.0.0/16 + network_zone: eu-central + type: cloud + state: present + +- name: Create a basic subnetwork + hcloud_subnetwork: + network: my-vswitch-network + ip_range: 10.0.0.0/24 + network_zone: eu-central + type: vswitch + vswitch_id: 123 + state: present + +- name: Ensure the subnetwork is absent (remove if needed) + hcloud_subnetwork: + network: my-network + ip_range: 10.0.0.0/8 + network_zone: eu-central + type: cloud + state: absent +""" + +RETURN = """ +hcloud_subnetwork: + description: One Subnet of a Network + returned: always + type: complex + contains: + network: + description: Name of the Network + type: str + returned: always + sample: my-network + ip_range: + description: IP range of the Network + type: str + returned: always + sample: 10.0.0.0/8 + type: + description: Type of subnetwork + type: str + returned: always + sample: server + network_zone: + description: Name of network zone + type: str + returned: always + sample: eu-central + vswitch_id: + description: ID of the vswitch, null if not type vswitch + type: int + returned: always + sample: 123 + gateway: + description: Gateway of the subnetwork + type: str + returned: always + sample: 10.0.0.1 +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException + from hcloud.networks.domain import NetworkSubnet +except ImportError: + APIException = None + NetworkSubnet = None + + +class AnsibleHcloudSubnetwork(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_subnetwork") + self.hcloud_network = None + self.hcloud_subnetwork = None + + def _prepare_result(self): + return { + "network": to_native(self.hcloud_network.name), + "ip_range": to_native(self.hcloud_subnetwork.ip_range), + "type": to_native(self.hcloud_subnetwork.type), + "network_zone": to_native(self.hcloud_subnetwork.network_zone), + "gateway": self.hcloud_subnetwork.gateway, + "vswitch_id": self.hcloud_subnetwork.vswitch_id, + } + + def _get_network(self): + try: + self.hcloud_network = self.client.networks.get_by_name(self.module.params.get("network")) + self.hcloud_subnetwork = None + except APIException as e: + self.module.fail_json(msg=e.message) + + def _get_subnetwork(self): + subnet_ip_range = self.module.params.get("ip_range") + for subnetwork in self.hcloud_network.subnets: + if subnetwork.ip_range == subnet_ip_range: + self.hcloud_subnetwork = subnetwork + + def _create_subnetwork(self): + params = { + "ip_range": self.module.params.get("ip_range"), + "type": self.module.params.get('type'), + "network_zone": self.module.params.get('network_zone') + } + if self.module.params.get('type') == NetworkSubnet.TYPE_VSWITCH: + self.module.fail_on_missing_params( + required_params=["vswitch_id"] + ) + params["vswitch_id"] = self.module.params.get('vswitch_id') + + if not self.module.check_mode: + try: + self.hcloud_network.add_subnet(subnet=NetworkSubnet(**params)).wait_until_finished() + except APIException as e: + self.module.fail_json(msg=e.message) + + self._mark_as_changed() + self._get_network() + self._get_subnetwork() + + def present_subnetwork(self): + self._get_network() + self._get_subnetwork() + if self.hcloud_subnetwork is None: + self._create_subnetwork() + + def delete_subnetwork(self): + self._get_network() + self._get_subnetwork() + if self.hcloud_subnetwork is not None and self.hcloud_network is not None: + if not self.module.check_mode: + self.hcloud_network.delete_subnet(self.hcloud_subnetwork).wait_until_finished() + self._mark_as_changed() + self.hcloud_subnetwork = None + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + network={"type": "str", "required": True}, + network_zone={"type": "str", "required": True}, + type={ + "type": "str", + "required": True, + "choices": ["server", "cloud", "vswitch"] + }, + ip_range={"type": "str", "required": True}, + vswitch_id={"type": "int"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudSubnetwork.define_module() + + hcloud = AnsibleHcloudSubnetwork(module) + state = module.params["state"] + if state == "absent": + hcloud.delete_subnetwork() + elif state == "present": + hcloud.present_subnetwork() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume.py new file mode 100644 index 00000000..28359373 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume.py @@ -0,0 +1,345 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_volume + +short_description: Create and manage block Volume on the Hetzner Cloud. + + +description: + - Create, update and attach/detach block Volume on the Hetzner Cloud. + +author: + - Christopher Schmitt (@cschmitt-hcloud) + +options: + id: + description: + - The ID of the Hetzner Cloud Block Volume to manage. + - Only required if no volume I(name) is given + type: int + name: + description: + - The Name of the Hetzner Cloud Block Volume to manage. + - Only required if no volume I(id) is given or a volume does not exists. + type: str + size: + description: + - The size of the Block Volume in GB. + - Required if volume does not yet exists. + type: int + automount: + description: + - Automatically mount the Volume. + type: bool + default: False + format: + description: + - Automatically Format the volume on creation + - Can only be used in case the Volume does not exists. + type: str + choices: [xfs, ext4] + location: + description: + - Location of the Hetzner Cloud Volume. + - Required if no I(server) is given and Volume does not exists. + type: str + server: + description: + - Server Name the Volume should be assigned to. + - Required if no I(location) is given and Volume does not exists. + type: str + delete_protection: + description: + - Protect the Volume for deletion. + type: bool + labels: + description: + - User-defined key-value pairs. + type: dict + state: + description: + - State of the Volume. + default: present + choices: [absent, present] + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Create a Volume + hcloud_volume: + name: my-volume + location: fsn1 + size: 100 + state: present +- name: Create a Volume and format it with ext4 + hcloud_volume: + name: my-volume + location: fsn + format: ext4 + size: 100 + state: present +- name: Mount a existing Volume and automount + hcloud_volume: + name: my-volume + server: my-server + automount: yes + state: present +- name: Mount a existing Volume and automount + hcloud_volume: + name: my-volume + server: my-server + automount: yes + state: present +- name: Ensure the Volume is absent (remove if needed) + hcloud_volume: + name: my-volume + state: absent +""" + +RETURN = """ +hcloud_volume: + description: The block Volume + returned: Always + type: complex + contains: + id: + description: ID of the Volume + type: int + returned: Always + sample: 12345 + name: + description: Name of the Volume + type: str + returned: Always + sample: my-volume + size: + description: Size in GB of the Volume + type: int + returned: Always + sample: 1337 + linux_device: + description: Path to the device that contains the Volume. + returned: always + type: str + sample: /dev/disk/by-id/scsi-0HC_Volume_12345 + version_added: "0.1.0" + location: + description: Location name where the Volume is located at + type: str + returned: Always + sample: "fsn1" + labels: + description: User-defined labels (key-value pairs) + type: dict + returned: Always + sample: + key: value + mylabel: 123 + server: + description: Server name where the Volume is attached to + type: str + returned: Always + sample: "my-server" + delete_protection: + description: True if Volume is protected for deletion + type: bool + returned: always + sample: false + version_added: "0.1.0" +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud.volumes.domain import Volume + from hcloud.servers.domain import Server + import hcloud +except ImportError: + APIException = None + Volume = None + Server = None + + +class AnsibleHcloudVolume(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_volume") + self.hcloud_volume = None + + def _prepare_result(self): + server_name = None + if self.hcloud_volume.server is not None: + server_name = self.hcloud_volume.server.name + + return { + "id": to_native(self.hcloud_volume.id), + "name": to_native(self.hcloud_volume.name), + "size": self.hcloud_volume.size, + "location": to_native(self.hcloud_volume.location.name), + "labels": self.hcloud_volume.labels, + "server": to_native(server_name), + "linux_device": to_native(self.hcloud_volume.linux_device), + "delete_protection": self.hcloud_volume.protection["delete"], + } + + def _get_volume(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_volume = self.client.volumes.get_by_id( + self.module.params.get("id") + ) + else: + self.hcloud_volume = self.client.volumes.get_by_name( + self.module.params.get("name") + ) + except hcloud.APIException as e: + self.module.fail_json(msg=e.message) + + def _create_volume(self): + self.module.fail_on_missing_params( + required_params=["name", "size"] + ) + params = { + "name": self.module.params.get("name"), + "size": self.module.params.get("size"), + "automount": self.module.params.get("automount"), + "format": self.module.params.get("format"), + "labels": self.module.params.get("labels") + } + if self.module.params.get("server") is not None: + params['server'] = self.client.servers.get_by_name(self.module.params.get("server")) + elif self.module.params.get("location") is not None: + params['location'] = self.client.locations.get_by_name(self.module.params.get("location")) + else: + self.module.fail_json(msg="server or location is required") + + if not self.module.check_mode: + resp = self.client.volumes.create(**params) + resp.action.wait_until_finished() + [action.wait_until_finished() for action in resp.next_actions] + delete_protection = self.module.params.get("delete_protection") + if delete_protection is not None: + self._get_volume() + self.hcloud_volume.change_protection(delete=delete_protection).wait_until_finished() + + self._mark_as_changed() + self._get_volume() + + def _update_volume(self): + try: + size = self.module.params.get("size") + if size: + if self.hcloud_volume.size < size: + if not self.module.check_mode: + self.hcloud_volume.resize(size).wait_until_finished() + self._mark_as_changed() + elif self.hcloud_volume.size > size: + self.module.warn("Shrinking of volumes is not supported") + + server_name = self.module.params.get("server") + if server_name: + server = self.client.servers.get_by_name(server_name) + if self.hcloud_volume.server is None or self.hcloud_volume.server.name != server.name: + if not self.module.check_mode: + automount = self.module.params.get("automount", False) + self.hcloud_volume.attach(server, automount=automount).wait_until_finished() + self._mark_as_changed() + else: + if self.hcloud_volume.server is not None: + if not self.module.check_mode: + self.hcloud_volume.detach().wait_until_finished() + self._mark_as_changed() + + labels = self.module.params.get("labels") + if labels is not None and labels != self.hcloud_volume.labels: + if not self.module.check_mode: + self.hcloud_volume.update(labels=labels) + self._mark_as_changed() + + delete_protection = self.module.params.get("delete_protection") + if delete_protection is not None and delete_protection != self.hcloud_volume.protection["delete"]: + if not self.module.check_mode: + self.hcloud_volume.change_protection(delete=delete_protection).wait_until_finished() + self._mark_as_changed() + + self._get_volume() + except hcloud.APIException as e: + self.module.fail_json(msg=e.message) + + def present_volume(self): + self._get_volume() + if self.hcloud_volume is None: + self._create_volume() + else: + self._update_volume() + + def delete_volume(self): + try: + self._get_volume() + if self.hcloud_volume is not None: + if not self.module.check_mode: + self.client.volumes.delete(self.hcloud_volume) + self._mark_as_changed() + self.hcloud_volume = None + except hcloud.APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + size={"type": "int"}, + location={"type": "str"}, + server={"type": "str"}, + labels={"type": "dict"}, + automount={"type": "bool", "default": False}, + format={"type": "str", + "choices": ['xfs', 'ext4'], + }, + delete_protection={"type": "bool"}, + state={ + "choices": ["absent", "present"], + "default": "present", + }, + **Hcloud.base_module_arguments() + ), + required_one_of=[['id', 'name']], + mutually_exclusive=[["location", "server"]], + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudVolume.define_module() + + hcloud = AnsibleHcloudVolume(module) + state = module.params.get("state") + if state == "absent": + module.fail_on_missing_params( + required_params=["name"] + ) + hcloud.delete_volume() + else: + hcloud.present_volume() + + module.exit_json(**hcloud.get_result()) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_facts.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_facts.py new file mode 100644 index 00000000..3006ea5e --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_facts.py @@ -0,0 +1,191 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_volume_info + +short_description: Gather infos about your Hetzner Cloud Volumes. + +description: + - Gather infos about your Hetzner Cloud Volumes. + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the Volume you want to get. + type: int + name: + description: + - The name of the Volume you want to get. + type: str + label_selector: + description: + - The label selector for the Volume you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud Volume infos + hcloud_volume_info: + register: output +- name: Print the gathered infos + debug: + var: output.hcloud_volume_info +""" + +RETURN = """ +hcloud_volume_info: + description: The Volume infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the Volume + returned: always + type: int + sample: 1937415 + name: + description: Name of the Volume + returned: always + type: str + sample: my-volume + size: + description: Size of the Volume + returned: always + type: str + sample: 10 + linux_device: + description: Path to the device that contains the Volume. + returned: always + type: str + sample: /dev/disk/by-id/scsi-0HC_Volume_12345 + version_added: "0.1.0" + location: + description: Name of the location where the Volume resides in + returned: always + type: str + sample: fsn1 + server: + description: Name of the server where the Volume is attached to + returned: always + type: str + sample: my-server + delete_protection: + description: True if the Volume is protected for deletion + returned: always + type: bool + version_added: "0.1.0" + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudVolumeInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_volume_info") + self.hcloud_volume_info = None + + def _prepare_result(self): + tmp = [] + + for volume in self.hcloud_volume_info: + if volume is not None: + server_name = None + if volume.server is not None: + server_name = volume.server.name + tmp.append({ + "id": to_native(volume.id), + "name": to_native(volume.name), + "size": volume.size, + "location": to_native(volume.location.name), + "labels": volume.labels, + "server": to_native(server_name), + "linux_device": to_native(volume.linux_device), + "delete_protection": volume.protection["delete"], + }) + + return tmp + + def get_volumes(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_volume_info = [self.client.volumes.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_volume_info = [self.client.volumes.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_volume_info = self.client.volumes.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_volume_info = self.client.volumes.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudVolumeInfo.define_module() + + is_old_facts = module._name == 'hcloud_volume_facts' + if is_old_facts: + module.deprecate("The 'hcloud_volume_facts' module has been renamed to 'hcloud_volume_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudVolumeInfo(module) + + hcloud.get_volumes() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_volume_facts': result['hcloud_volume_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_volume_info': result['hcloud_volume_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_info.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_info.py new file mode 100644 index 00000000..3006ea5e --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/plugins/modules/hcloud_volume_info.py @@ -0,0 +1,191 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: hcloud_volume_info + +short_description: Gather infos about your Hetzner Cloud Volumes. + +description: + - Gather infos about your Hetzner Cloud Volumes. + +author: + - Lukas Kaemmerling (@LKaemmerling) + +options: + id: + description: + - The ID of the Volume you want to get. + type: int + name: + description: + - The name of the Volume you want to get. + type: str + label_selector: + description: + - The label selector for the Volume you want to get. + type: str +extends_documentation_fragment: +- hetzner.hcloud.hcloud + +''' + +EXAMPLES = """ +- name: Gather hcloud Volume infos + hcloud_volume_info: + register: output +- name: Print the gathered infos + debug: + var: output.hcloud_volume_info +""" + +RETURN = """ +hcloud_volume_info: + description: The Volume infos as list + returned: always + type: complex + contains: + id: + description: Numeric identifier of the Volume + returned: always + type: int + sample: 1937415 + name: + description: Name of the Volume + returned: always + type: str + sample: my-volume + size: + description: Size of the Volume + returned: always + type: str + sample: 10 + linux_device: + description: Path to the device that contains the Volume. + returned: always + type: str + sample: /dev/disk/by-id/scsi-0HC_Volume_12345 + version_added: "0.1.0" + location: + description: Name of the location where the Volume resides in + returned: always + type: str + sample: fsn1 + server: + description: Name of the server where the Volume is attached to + returned: always + type: str + sample: my-server + delete_protection: + description: True if the Volume is protected for deletion + returned: always + type: bool + version_added: "0.1.0" + labels: + description: User-defined labels (key-value pairs) + returned: always + type: dict +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native +from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import Hcloud + +try: + from hcloud import APIException +except ImportError: + APIException = None + + +class AnsibleHcloudVolumeInfo(Hcloud): + def __init__(self, module): + Hcloud.__init__(self, module, "hcloud_volume_info") + self.hcloud_volume_info = None + + def _prepare_result(self): + tmp = [] + + for volume in self.hcloud_volume_info: + if volume is not None: + server_name = None + if volume.server is not None: + server_name = volume.server.name + tmp.append({ + "id": to_native(volume.id), + "name": to_native(volume.name), + "size": volume.size, + "location": to_native(volume.location.name), + "labels": volume.labels, + "server": to_native(server_name), + "linux_device": to_native(volume.linux_device), + "delete_protection": volume.protection["delete"], + }) + + return tmp + + def get_volumes(self): + try: + if self.module.params.get("id") is not None: + self.hcloud_volume_info = [self.client.volumes.get_by_id( + self.module.params.get("id") + )] + elif self.module.params.get("name") is not None: + self.hcloud_volume_info = [self.client.volumes.get_by_name( + self.module.params.get("name") + )] + elif self.module.params.get("label_selector") is not None: + self.hcloud_volume_info = self.client.volumes.get_all( + label_selector=self.module.params.get("label_selector")) + else: + self.hcloud_volume_info = self.client.volumes.get_all() + + except APIException as e: + self.module.fail_json(msg=e.message) + + @staticmethod + def define_module(): + return AnsibleModule( + argument_spec=dict( + id={"type": "int"}, + name={"type": "str"}, + label_selector={"type": "str"}, + **Hcloud.base_module_arguments() + ), + supports_check_mode=True, + ) + + +def main(): + module = AnsibleHcloudVolumeInfo.define_module() + + is_old_facts = module._name == 'hcloud_volume_facts' + if is_old_facts: + module.deprecate("The 'hcloud_volume_facts' module has been renamed to 'hcloud_volume_info', " + "and the renamed one no longer returns ansible_facts", version='2.0.0', collection_name="hetzner.hcloud") + + hcloud = AnsibleHcloudVolumeInfo(module) + + hcloud.get_volumes() + result = hcloud.get_result() + if is_old_facts: + ansible_info = { + 'hcloud_volume_facts': result['hcloud_volume_info'] + } + module.exit_json(ansible_facts=ansible_info) + else: + ansible_info = { + 'hcloud_volume_info': result['hcloud_volume_info'] + } + module.exit_json(**ansible_info) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/shippable.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/shippable.yml new file mode 100644 index 00000000..885c3817 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/shippable.yml @@ -0,0 +1,56 @@ +language: python + +python: 3.7 +env: + matrix: + - T=none + +matrix: + exclude: + - env: T=none + include: + - env: T=devel/sanity/1 + python: 3.7 + - env: T=devel/sanity/2 + python: 3.7 + - env: T=devel/sanity/3 + python: 3.7 + - env: T=devel/sanity/4 + python: 3.7 + + - env: T=devel/hcloud/3.8/1 + - env: T=devel/hcloud/3.8/2 + + + - env: T=2.10/sanity/1 + - env: T=2.10/sanity/2 + - env: T=2.10/sanity/3 + - env: T=2.10/sanity/4 + + - env: T=2.10/hcloud/3.8/1 + - env: T=2.10/hcloud/3.8/2 + - env: T=2.10/hcloud/3.8/3 + + + - env: T=2.9/sanity/1 + - env: T=2.9/sanity/2 + - env: T=2.9/sanity/3 + - env: T=2.9/sanity/4 + +branches: + except: + - "*-patch-*" + - "revert-*-*" + +build: + ci: + - tests/utils/shippable/timing.sh tests/utils/shippable/shippable.sh $T + +integrations: + notifications: + - integrationName: email + type: email + on_success: never + on_failure: never + on_start: never + on_pull_request: never diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/.gitignore b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/.gitignore new file mode 100644 index 00000000..ea1472ec --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/.gitignore @@ -0,0 +1 @@ +output/ diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/requirements.txt b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/requirements.txt new file mode 100644 index 00000000..d3249def --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/requirements.txt @@ -0,0 +1,2 @@ +netaddr +hcloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/defaults/main.yml new file mode 100644 index 00000000..49b6c6fb --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_certificate_name: "{{hcloud_prefix}}-integration" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/meta/main.yml new file mode 100644 index 00000000..e531064c --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/meta/main.yml @@ -0,0 +1,5 @@ +dependencies: + - setup_selfsigned_certificate +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/tasks/main.yml new file mode 100644 index 00000000..5f6376e9 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate/tasks/main.yml @@ -0,0 +1,123 @@ +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: test missing required parameters on create certificate + hcloud_certificate: + name: "{{ hcloud_certificate_name }}" + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create certificate + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: certificate, private_key"' + +- name: test create certificate with check mode + hcloud_certificate: + name: "{{ hcloud_certificate_name }}" + certificate: "{{ certificate_example_com }}" + private_key: "{{ certificate_example_com_key }}" + register: result + check_mode: yes +- name: test create certificate with check mode + assert: + that: + - result is changed + +- name: test create certificate + hcloud_certificate: + name: "{{ hcloud_certificate_name }}" + certificate: "{{ certificate_example_com }}" + private_key: "{{ certificate_example_com_key }}" + labels: + key: value + my-label: label + register: certificate +- name: verify create certificate + assert: + that: + - certificate is changed + - certificate.hcloud_certificate.name == "{{ hcloud_certificate_name }}" + - certificate.hcloud_certificate.domain_names[0] == "www.example.com" + - certificate.hcloud_certificate.labels.key == "value" + +- name: test create certificate idempotence + hcloud_certificate: + name: "{{ hcloud_certificate_name }}" + certificate: "{{ certificate_example_com }}" + private_key: "{{ certificate_example_com_key }}" + register: result +- name: verify create certificate idempotence + assert: + that: + - result is not changed + +- name: test update certificate with check mode + hcloud_certificate: + id: "{{ certificate.hcloud_certificate.id }}" + name: "changed-{{ hcloud_certificate_name }}" + register: result + check_mode: yes +- name: test create certificate with check mode + assert: + that: + - result is changed + +- name: test update certificate + hcloud_certificate: + id: "{{ certificate.hcloud_certificate.id }}" + name: "changed-{{ hcloud_certificate_name }}" + labels: + key: value + register: result +- name: test update certificate + assert: + that: + - result is changed + - result.hcloud_certificate.name == "changed-{{ hcloud_certificate_name }}" + +- name: test update certificate with same labels + hcloud_certificate: + id: "{{ certificate.hcloud_certificate.id }}" + name: "changed-{{ hcloud_certificate_name }}" + labels: + key: value + register: result +- name: test update certificate with same labels + assert: + that: + - result is not changed + +- name: test update certificate with other labels + hcloud_certificate: + id: "{{ certificate.hcloud_certificate.id }}" + name: "changed-{{ hcloud_certificate_name }}" + labels: + key: value + test: "val123" + register: result +- name: test update certificate with other labels + assert: + that: + - result is changed + +- name: test rename certificate + hcloud_certificate: + id: "{{ certificate.hcloud_certificate.id }}" + name: "{{ hcloud_certificate_name }}" + register: result +- name: test rename certificate + assert: + that: + - result is changed + - result.hcloud_certificate.name == "{{ hcloud_certificate_name }}" + +- name: absent certificate + hcloud_certificate: + id: "{{ certificate.hcloud_certificate.id }}" + state: absent + register: result +- name: verify absent server + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/defaults/main.yml new file mode 100644 index 00000000..6205b19b --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_certificate_name: "always-there-cert" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/meta/main.yml new file mode 100644 index 00000000..f830a9da --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/meta/main.yml @@ -0,0 +1,2 @@ +collections: + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/tasks/main.yml new file mode 100644 index 00000000..7dc4eb72 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_certificate_info/tasks/main.yml @@ -0,0 +1,39 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- + +- name: test gather hcloud certificate infos in check mode + hcloud_certificate_info: + register: hcloud_certificate + check_mode: yes +- name: verify test gather hcloud certificate infos in check mode + assert: + that: + - hcloud_certificate.hcloud_certificate_info| list | count >= 1 + +- name: test gather hcloud certificate infos + hcloud_certificate_info: + register: hcloud_certificate + check_mode: yes +- name: verify test gather hcloud certificate infos + assert: + that: + - hcloud_certificate.hcloud_certificate_info| list | count >= 1 + +- name: test gather hcloud certificate infos with correct label selector + hcloud_certificate_info: + label_selector: "key=value" + register: hcloud_certificate +- name: verify test gather hcloud certificate infos with correct label selector + assert: + that: + - hcloud_certificate.hcloud_certificate_info|selectattr('name','equalto','{{ hcloud_certificate_name }}') | list | count == 1 + +- name: test gather hcloud certificate infos with wrong label selector + hcloud_certificate_info: + label_selector: "key!=value" + register: hcloud_certificate +- name: verify test gather hcloud certificate infos with wrong label selector + assert: + that: + - hcloud_certificate.hcloud_certificate_info | list | count == 0 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/defaults/main.yml new file mode 100644 index 00000000..b9e045f4 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_datacenter_name: "fsn1-dc14" +hcloud_datacenter_id: 4 +hcloud_location_name: "fsn1" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/tasks/main.yml new file mode 100644 index 00000000..7f49b040 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_datacenter_info/tasks/main.yml @@ -0,0 +1,40 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: test gather hcloud datacenter infos + hcloud_datacenter_info: + register: hcloud_datacenters + +- name: verify test gather hcloud datacenter infos + assert: + that: + - hcloud_datacenters.hcloud_datacenter_info| list | count == 3 + +- name: test gather hcloud datacenter infos in check mode + hcloud_datacenter_info: + register: hcloud_datacenters + check_mode: yes + +- name: verify test gather hcloud datacenter infos in check mode + assert: + that: + - hcloud_datacenters.hcloud_datacenter_info| list | count == 3 + + +- name: test gather hcloud datacenter infos with correct name + hcloud_datacenter_info: + name: "{{hcloud_datacenter_name}}" + register: hcloud_datacenter +- name: verify test gather hcloud datacenter with correct name + assert: + that: + - hcloud_datacenter.hcloud_datacenter_info|selectattr('name','equalto','{{ hcloud_datacenter_name }}') |selectattr('location','equalto','{{ hcloud_location_name }}') | list | count == 1 + +- name: test gather hcloud datacenter infos with correct id + hcloud_datacenter_info: + id: "{{hcloud_datacenter_id}}" + register: hcloud_datacenter +- name: verify test gather hcloud datacenter with correct id + assert: + that: + - hcloud_datacenter.hcloud_datacenter_info|selectattr('name','equalto','{{ hcloud_datacenter_name }}') | list | count == 1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/defaults/main.yml new file mode 100644 index 00000000..fc60d281 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_floating_ip_name: "{{hcloud_prefix}}-integration" +hcloud_server_name: "{{hcloud_prefix}}-fip-tests"
\ No newline at end of file diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/tasks/main.yml new file mode 100644 index 00000000..70f23e33 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip/tasks/main.yml @@ -0,0 +1,443 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup server + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: cx11 + image: ubuntu-18.04 + state: started + location: "fsn1" + register: main_server +- name: verify setup server + assert: + that: + - main_server is changed + +- name: setup another server + hcloud_server: + name: "{{ hcloud_server_name }}2" + server_type: cx11 + image: ubuntu-18.04 + state: started + register: main_server2 +- name: verify setup another server + assert: + that: + - main_server2 is changed + +- name: test missing type parameter on create Floating IP + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + register: result + ignore_errors: yes +- name: verify fail test missing type parameter on create Floating IP + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: type"' + +- name: test missing required parameters on create Floating IP + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create Floating IP + assert: + that: + - result is failed + - 'result.msg == "one of the following is required: home_location, server"' + +- name: test missing type parameter on delete Floating IP + hcloud_floating_ip: + type: ipv4 + home_location: "fsn1" + state: "absent" + register: result + ignore_errors: yes +- name: verify fail test missing type parameter on delete Floating IP + assert: + that: + - result is failed + - 'result.msg == "one of the following is required: id, name"' + +- name: test create Floating IP with check mode + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "Web Server" + type: ipv4 + home_location: "fsn1" + register: floatingIP + check_mode: yes +- name: verify test create Floating IP with check mode + assert: + that: + - floatingIP is changed + +- name: test create Floating IP + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "Web Server" + type: ipv4 + home_location: "fsn1" + register: floatingIP +- name: verify test create Floating IP + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.name ==hcloud_floating_ip_name + - floatingIP.hcloud_floating_ip.description == "Web Server" + - floatingIP.hcloud_floating_ip.home_location == "fsn1" + +- name: test create Floating IP idempotency + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "Web Server" + type: ipv4 + home_location: "fsn1" + register: floatingIP +- name: verify test create Floating IP idempotency + assert: + that: + - floatingIP is not changed + +- name: test update Floating IP with check mode + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "changed-description" + type: ipv4 + home_location: "fsn1" + check_mode: yes + register: floatingIP +- name: verify test create Floating IP with check mode + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.description == "Web Server" + +- name: test update Floating IP + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "changed-description" + type: ipv4 + home_location: "fsn1" + labels: + key: value + register: floatingIP +- name: verify test update Floating IP + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.description == "changed-description" + +- name: test update Floating IP idempotency + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "changed-description" + type: ipv4 + home_location: "fsn1" + labels: + key: value + register: floatingIP +- name: verify test update Floating IP idempotency + assert: + that: + - floatingIP is not changed + +- name: test update Floating IP with same labels + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + home_location: "fsn1" + labels: + key: value + register: floatingIP +- name: verify test update Floating IP with same labels + assert: + that: + - floatingIP is not changed + +- name: test update Floating IP with other labels + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + home_location: "fsn1" + labels: + key: value + other: label + register: floatingIP +- name: verify test update Floating IP with other labels + assert: + that: + - floatingIP is changed + +- name: test update Floating IP with other labels in different order + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + home_location: "fsn1" + labels: + other: label + key: value + register: floatingIP +- name: verify test update Floating IP with other labels in different order + assert: + that: + - floatingIP is not changed + +- name: test assign Floating IP with checkmode + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "changed-description" + type: ipv4 + server: "{{ main_server.hcloud_server.name }}" + check_mode: yes + register: floatingIP +- name: verify test assign Floating IP with checkmode + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.server != "{{ main_server.hcloud_server.name }}" + +- name: test assign Floating IP + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "changed-description" + type: ipv4 + server: "{{ main_server.hcloud_server.name }}" + register: floatingIP +- name: verify test assign Floating IP + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.server == "{{ main_server.hcloud_server.name }}" + +- name: test assign Floating IP idempotency + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + description: "changed-description" + type: ipv4 + server: "{{ main_server.hcloud_server.name }}" + register: floatingIP +- name: verify test unassign Floating IPidempotency + assert: + that: + - floatingIP is not changed + +- name: test unassign Floating IP + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + home_location: "fsn1" + register: floatingIP +- name: verify test unassign Floating IP + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.server != "{{ main_server.hcloud_server.name }}" + +- name: test unassign Floating IP idempotency + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + home_location: "fsn1" + register: floatingIP +- name: verify test unassign Floating IPidempotency + assert: + that: + - floatingIP is not changed + +- name: test assign Floating IP again + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + server: "{{ main_server.hcloud_server.name }}" + register: floatingIP +- name: verify test assign Floating IP again + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.server == "{{ main_server.hcloud_server.name }}" + +- name: test already assigned Floating IP assign without force + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + server: "{{ main_server2.hcloud_server.name }}" + register: floatingIP +- name: verify test already assigned Floating IP assign without force + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.server == "{{ main_server.hcloud_server.name }}" + +- name: test already assigned Floating IP assign with force + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + force: yes + server: "{{ main_server2.hcloud_server.name }}" + register: floatingIP +- name: verify test already assigned Floating IP assign with force + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.server == "{{ main_server2.hcloud_server.name }}" + +- name: test update Floating IP delete protection + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + delete_protection: true + register: floatingIP +- name: verify update Floating IP delete protection + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.delete_protection is sameas true + +- name: test update Floating IP delete protection idempotency + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + delete_protection: true + register: floatingIP +- name: verify update Floating IP delete protection idempotency + assert: + that: + - floatingIP is not changed + - floatingIP.hcloud_floating_ip.delete_protection is sameas true + +- name: test Floating IP without delete protection set to be idempotent + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + register: floatingIP +- name: verify Floating IP without delete protection set to be idempotent + assert: + that: + - floatingIP is not changed + - floatingIP.hcloud_floating_ip.delete_protection is sameas true + +- name: test delete Floating IP fails if it is protected + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + state: "absent" + register: result + ignore_errors: yes +- name: verify test delete floating ip + assert: + that: + - result is failed + - 'result.msg == "Floating IP deletion is protected"' + +- name: test update Floating IP delete protection + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + delete_protection: false + register: floatingIP +- name: verify update Floating IP delete protection + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.delete_protection is sameas false + +- name: test delete floating ip + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + state: "absent" + register: result +- name: verify test delete floating ip + assert: + that: + - result is changed + +- name: test create ipv6 floating ip + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv6 + home_location: "fsn1" + state: "present" + register: result +- name: verify test create ipv6 floating ip + assert: + that: + - result is changed + +- name: test delete ipv6 floating ip + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + state: "absent" + register: result +- name: verify test delete ipv6 floating ip + assert: + that: + - result is changed + +- name: cleanup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is changed +- name: cleanup another server + hcloud_server: + name: "{{ main_server2.hcloud_server.name }}" + state: absent + register: result +- name: verify cleanup another server + assert: + that: + - result is changed + +- name: test create Floating IP with delete protection + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + home_location: fsn1 + delete_protection: true + register: floatingIP +- name: verify create Floating IP with delete protection + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.delete_protection is sameas true + +- name: test delete Floating IP fails if it is protected + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + state: "absent" + register: result + ignore_errors: yes +- name: verify test delete floating ip + assert: + that: + - result is failed + - 'result.msg == "Floating IP deletion is protected"' + +- name: test update Floating IP delete protection + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + delete_protection: false + register: floatingIP +- name: verify update Floating IP delete protection + assert: + that: + - floatingIP is changed + - floatingIP.hcloud_floating_ip.delete_protection is sameas false + +- name: test delete floating ip + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + state: "absent" + register: result +- name: verify test delete floating ip + assert: + that: + - result is changed diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/defaults/main.yml new file mode 100644 index 00000000..2a21de73 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_floating_ip_name: "{{hcloud_prefix}}-integration" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml new file mode 100644 index 00000000..9ca1c2a4 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_floating_ip_info/tasks/main.yml @@ -0,0 +1,87 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup ensure floating ip is absent + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + state: absent + +- name: setup floating ip + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + home_location: "fsn1" + type: ipv4 + labels: + key: value + register: test_floating_ip + +- name: verify setup floating ip + assert: + that: + - test_floating_ip is changed + +- name: test gather hcloud floating ip infos + hcloud_floating_ip_info: + register: hcloud_floating_ips +- name: verify test gather hcloud floating ip infos + assert: + that: + - hcloud_floating_ips.hcloud_floating_ip_info| list | count >= 1 + +- name: test gather hcloud floating ip infos in check mode + hcloud_floating_ip_info: + check_mode: yes + register: hcloud_floating_ips + +- name: verify test gather hcloud floating ip infos in check mode + assert: + that: + - hcloud_floating_ips.hcloud_floating_ip_info| list | count >= 1 + + +- name: test gather hcloud floating ip infos with correct label selector + hcloud_floating_ip_info: + label_selector: "key=value" + register: hcloud_floating_ips +- name: verify test gather hcloud floating ip with correct label selector + assert: + that: + - hcloud_floating_ips.hcloud_floating_ip_info|selectattr('name','equalto','{{ test_floating_ip.hcloud_floating_ip.name }}') | list | count == 1 + +- name: test gather hcloud floating ip infos with wrong label selector + hcloud_floating_ip_info: + label_selector: "key!=value" + register: hcloud_floating_ips +- name: verify test gather hcloud floating ip with wrong label selector + assert: + that: + - hcloud_floating_ips.hcloud_floating_ip_info | list | count == 0 + +- name: test gather hcloud floating ip infos with correct id + hcloud_floating_ip_info: + id: "{{test_floating_ip.hcloud_floating_ip.id}}" + register: hcloud_floating_ips +- name: verify test gather hcloud floating ip with correct id + assert: + that: + - hcloud_floating_ips.hcloud_floating_ip_info|selectattr('name','equalto','{{ test_floating_ip.hcloud_floating_ip.name }}') | list | count == 1 + +- name: test gather hcloud floating ip infos with wrong id + hcloud_floating_ip_info: + id: "{{test_floating_ip.hcloud_floating_ip.id}}1" + register: result + ignore_errors: yes +- name: verify test gather hcloud floating ip with wrong id + assert: + that: + - result is failed + +- name: cleanup + hcloud_floating_ip: + id: "{{ test_floating_ip.hcloud_floating_ip.id }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/defaults/main.yml new file mode 100644 index 00000000..ddca3328 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_test_image_name: "always-there-snapshot" +hcloud_test_image_id: 10164049 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/tasks/main.yml new file mode 100644 index 00000000..503d5b78 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_image_info/tasks/main.yml @@ -0,0 +1,62 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: test gather hcloud image infos with type system + hcloud_image_info: + register: hcloud_images +- name: verify test gather hcloud image infos in check mode + assert: + that: + - hcloud_images.hcloud_image_info| list | count > 2 + +- name: test gather hcloud image infos in check mode + hcloud_image_info: + check_mode: yes + register: hcloud_images + +- name: verify test gather hcloud image infos in check mode + assert: + that: + - hcloud_images.hcloud_image_info| list | count > 2 + + +- name: test gather hcloud image infos with correct label selector + hcloud_image_info: + label_selector: "key=value" + type: snapshot + register: hcloud_images +- name: verify test gather hcloud image with correct label selector + assert: + that: + - hcloud_images.hcloud_image_info|selectattr('description','equalto','{{ hcloud_test_image_name }}') | list | count == 1 + +- name: test gather hcloud image infos with wrong label selector + hcloud_image_info: + label_selector: "key!=value" + type: snapshot + register: hcloud_images +- name: verify test gather hcloud image with wrong label selector + assert: + that: + - hcloud_images.hcloud_image_info | list | count == 0 + +- name: test gather hcloud image infos with correct id + hcloud_image_info: + id: "{{hcloud_test_image_id}}" + type: snapshot + register: hcloud_images +- name: verify test gather hcloud image with correct id + assert: + that: + - hcloud_images.hcloud_image_info|selectattr('description','equalto','{{ hcloud_test_image_name }}') | list | count == 1 + +- name: test gather hcloud image infos with wrong id + hcloud_image_info: + id: "{{hcloud_test_image_id}}1" + type: snapshot + ignore_errors: yes + register: result +- name: verify test gather hcloud image with wrong id + assert: + that: + - result is failed diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/defaults/main.yml new file mode 100644 index 00000000..38e96f6d --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_load_balancer_name: "{{hcloud_prefix}}-integration" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/tasks/main.yml new file mode 100644 index 00000000..a25e550d --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer/tasks/main.yml @@ -0,0 +1,247 @@ +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: absent + register: result +- name: verify setup + assert: + that: + - result is success +- name: test missing required parameters on create Load Balancer + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create Load Balancer + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: load_balancer_type"' + +- name: test create Load Balancer with check mode + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + load_balancer_type: lb11 + network_zone: eu-central + state: present + register: result + check_mode: yes +- name: test create Load Balancer with check mode + assert: + that: + - result is changed + +- name: test create Load Balancer + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name}}" + load_balancer_type: lb11 + network_zone: eu-central + state: present + register: main_load_balancer +- name: verify create Load Balancer + assert: + that: + - main_load_balancer is changed + - main_load_balancer.hcloud_load_balancer.name == "{{ hcloud_load_balancer_name }}" + - main_load_balancer.hcloud_load_balancer.load_balancer_type == "lb11" + +- name: test create Load Balancer idempotence + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + load_balancer_type: lb11 + network_zone: eu-central + state: present + register: result +- name: verify create Load Balancer idempotence + assert: + that: + - result is not changed + +- name: test change Load Balancer type + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + load_balancer_type: lb21 + state: present + register: result_after_test + ignore_errors: true +- name: verify change Load Balancer type + assert: + that: + - result_after_test is changed + - result_after_test.hcloud_load_balancer.load_balancer_type == "lb21" + +- name: test Load Balancer without type set to be idempotent + hcloud_load_balancer: + name: "{{hcloud_load_balancer_name}}" + register: result_after_test +- name: verify test Load Balancer without type set to be idempotent + assert: + that: + - result_after_test is not changed + - result_after_test.hcloud_load_balancer.load_balancer_type == "lb21" + +- name: test update Load Balancer protection + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + delete_protection: true + state: present + register: result_after_test + ignore_errors: true +- name: verify update Load Balancer protection + assert: + that: + - result_after_test is changed + - result_after_test.hcloud_load_balancer.delete_protection is sameas true + +- name: test Load Balancer without protection set to be idempotent + hcloud_load_balancer: + name: "{{hcloud_load_balancer_name}}" + register: result_after_test +- name: verify test Load Balancer without protection set to be idempotent + assert: + that: + - result_after_test is not changed + - result_after_test.hcloud_load_balancer.delete_protection is sameas true + +- name: test delete Load Balancer fails if it is protected + hcloud_load_balancer: + name: "{{hcloud_load_balancer_name}}" + state: absent + ignore_errors: yes + register: result +- name: verify delete Load Balancer fails if it is protected + assert: + that: + - result is failed + - 'result.msg == "load balancer deletion is protected"' + +- name: test remove Load Balancer protection + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + delete_protection: false + state: present + register: result_after_test + ignore_errors: true +- name: verify remove Load Balancer protection + assert: + that: + - result_after_test is changed + - result_after_test.hcloud_load_balancer.delete_protection is sameas false + +- name: absent Load Balancer + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: absent + register: result +- name: verify absent Load Balancer + assert: + that: + - result is success + +- name: test create Load Balancer with labels + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name}}" + load_balancer_type: lb11 + network_zone: eu-central + labels: + key: value + mylabel: "val123" + state: present + register: main_load_balancer +- name: verify create Load Balancer with labels + assert: + that: + - main_load_balancer is changed + - main_load_balancer.hcloud_load_balancer.labels.key == "value" + - main_load_balancer.hcloud_load_balancer.labels.mylabel == "val123" + +- name: test update Load Balancer with labels + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name}}" + load_balancer_type: lb11 + network_zone: eu-central + labels: + key: other + mylabel: "val123" + state: present + register: main_load_balancer +- name: verify update Load Balancer with labels + assert: + that: + - main_load_balancer is changed + - main_load_balancer.hcloud_load_balancer.labels.key == "other" + - main_load_balancer.hcloud_load_balancer.labels.mylabel == "val123" + +- name: test update Load Balancer with labels in other order + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name}}" + load_balancer_type: lb11 + network_zone: eu-central + labels: + mylabel: "val123" + key: other + state: present + register: main_load_balancer +- name: verify update Load Balancer with labels in other order + assert: + that: + - main_load_balancer is not changed + +- name: cleanup with labels + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success + +- name: test create Load Balancer with delete protection + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + load_balancer_type: lb11 + network_zone: eu-central + delete_protection: true + register: main_load_balancer +- name: verify create Load Balancer with delete protection + assert: + that: + - main_load_balancer is changed + - main_load_balancer.hcloud_load_balancer.delete_protection is sameas true + +- name: test delete Load Balancer fails if it is protected + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: "absent" + register: result + ignore_errors: yes +- name: verify test delete Load Balancer + assert: + that: + - result is failed + - 'result.msg == "load balancer deletion is protected"' + +- name: test update Load Balancer delete protection + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + delete_protection: false + register: main_load_balancer +- name: verify update Load Balancer delete protection + assert: + that: + - main_load_balancer is changed + - main_load_balancer.hcloud_load_balancer.delete_protection is sameas false + +- name: test delete Load Balancer + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: "absent" + register: result +- name: verify test delete Load Balancer + assert: + that: + - result is changed diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml new file mode 100644 index 00000000..b5e53281 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_load_balancer_name: "{{hcloud_prefix}}-integration" +hcloud_server_name: "{{hcloud_prefix}}-lb-info" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml new file mode 100644 index 00000000..9e652885 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_info/tasks/main.yml @@ -0,0 +1,128 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup ensure Load Balancer is absent + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: absent +- name: setup server + hcloud_server: + name: "{{hcloud_server_name}}" + server_type: cx11 + image: ubuntu-20.04 + state: started + register: server +- name: verify setup server + assert: + that: + - server is success +- name: setup Load Balancer + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + load_balancer_type: lb11 + network_zone: eu-central + labels: + key: value + register: test_load_balancer + +- name: verify setup Load Balancer + assert: + that: + - test_load_balancer is changed + +- name: test create load_balancer target + hcloud_load_balancer_target: + type: "server" + load_balancer: "{{hcloud_load_balancer_name}}" + server: "{{hcloud_server_name}}" + state: present + register: load_balancer_target +- name: verify create load_balancer target + assert: + that: + - load_balancer_target is success +- name: test create load_balancer service + hcloud_load_balancer_service: + load_balancer: "{{hcloud_load_balancer_name}}" + protocol: "http" + listen_port: 80 + state: present + register: load_balancer_service +- name: verify create load_balancer service + assert: + that: + - load_balancer_service is success + +- name: test gather hcloud Load Balancer infos + hcloud_load_balancer_info: + id: "{{test_load_balancer.hcloud_load_balancer.id}}" + register: hcloud_load_balancers +- name: verify test gather hcloud Load Balancer infos + assert: + that: + - hcloud_load_balancers.hcloud_load_balancer_info| list | count >= 1 + - hcloud_load_balancers.hcloud_load_balancer_info[0].targets | list | count == 1 + - hcloud_load_balancers.hcloud_load_balancer_info[0].targets | selectattr('type','equalto','server') | list | count == 1 + - hcloud_load_balancers.hcloud_load_balancer_info[0].targets | selectattr('server','equalto','{{ hcloud_server_name }}') | list | count == 1 + - hcloud_load_balancers.hcloud_load_balancer_info[0].services | list | count == 1 + - hcloud_load_balancers.hcloud_load_balancer_info[0].services | selectattr('protocol','equalto','http') | list | count == 1 + - hcloud_load_balancers.hcloud_load_balancer_info[0].services | selectattr('listen_port','equalto',80) | list | count == 1 + - hcloud_load_balancers.hcloud_load_balancer_info[0].services | selectattr('destination_port','equalto',80) | list | count == 1 + +- name: test gather hcloud Load Balancer infos in check mode + hcloud_load_balancer_info: + check_mode: yes + register: hcloud_load_balancers + +- name: verify test gather hcloud Load Balancer infos in check mode + assert: + that: + - hcloud_load_balancers.hcloud_load_balancer_info| list | count >= 1 + + +- name: test gather hcloud Load Balancer infos with correct label selector + hcloud_load_balancer_info: + label_selector: "key=value" + register: hcloud_load_balancers +- name: verify test gather hcloud Load Balancer with correct label selector + assert: + that: + - hcloud_load_balancers.hcloud_load_balancer_info|selectattr('name','equalto','{{ test_load_balancer.hcloud_load_balancer.name }}') | list | count == 1 + +- name: test gather hcloud Load Balancer infos with wrong label selector + hcloud_load_balancer_info: + label_selector: "key!=value" + register: hcloud_load_balancers +- name: verify test gather hcloud Load Balancer with wrong label selector + assert: + that: + - hcloud_load_balancers.hcloud_load_balancer_info | list | count == 0 + +- name: test gather hcloud Load Balancer infos with correct id + hcloud_load_balancer_info: + id: "{{test_load_balancer.hcloud_load_balancer.id}}" + register: hcloud_load_balancers +- name: verify test gather hcloud Load Balancer with correct id + assert: + that: + - hcloud_load_balancers.hcloud_load_balancer_info|selectattr('name','equalto','{{ test_load_balancer.hcloud_load_balancer.name }}') | list | count == 1 + +- name: test gather hcloud Load Balancer infos with wrong id + hcloud_load_balancer_info: + id: "{{test_load_balancer.hcloud_load_balancer.id}}1" + register: result + ignore_errors: yes +- name: verify test gather hcloud Load Balancer with wrong id + assert: + that: + - result is failed + +- name: cleanup + hcloud_load_balancer: + id: "{{ test_load_balancer.hcloud_load_balancer.id }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml new file mode 100644 index 00000000..8747bff4 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_network_name: "{{hcloud_prefix}}-load_balancer-network" +hcloud_load_balancer_name: "{{hcloud_prefix}}-load_balancer-network" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/tasks/main.yml new file mode 100644 index 00000000..76788ed8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_network/tasks/main.yml @@ -0,0 +1,155 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup network + hcloud_network: + name: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/8" + state: present + register: network +- name: verify setup network + assert: + that: + - network is success + +- name: setup subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "cloud" + network_zone: "eu-central" + state: present + register: subnetwork +- name: verify subnetwork + assert: + that: + - subnetwork is success + +- name: setup load_balancer + hcloud_load_balancer: + name: "{{hcloud_load_balancer_name}}" + load_balancer_type: lb11 + state: present + location: "fsn1" + register: load_balancer +- name: verify setup load_balancer + assert: + that: + - load_balancer is success + +- name: test missing required parameters on create load_balancer network + hcloud_load_balancer_network: + state: present + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create load_balancer network + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: load_balancer, network"' + +- name: test create load_balancer network with checkmode + hcloud_load_balancer_network: + network: "{{ hcloud_network_name }}" + load_balancer: "{{hcloud_load_balancer_name}}" + state: present + register: result + check_mode: yes +- name: verify test create load_balancer network with checkmode + assert: + that: + - result is changed + +- name: test create load_balancer network + hcloud_load_balancer_network: + network: "{{ hcloud_network_name }}" + load_balancer: "{{hcloud_load_balancer_name}}" + state: present + register: load_balancerNetwork +- name: verify create load_balancer network + assert: + that: + - load_balancerNetwork is changed + - load_balancerNetwork.hcloud_load_balancer_network.network == hcloud_network_name + - load_balancerNetwork.hcloud_load_balancer_network.load_balancer == hcloud_load_balancer_name + +- name: test create load_balancer network idempotency + hcloud_load_balancer_network: + network: "{{ hcloud_network_name }}" + load_balancer: "{{hcloud_load_balancer_name}}" + state: present + register: load_balancerNetwork +- name: verify create load_balancer network idempotency + assert: + that: + - load_balancerNetwork is not changed + +- name: test absent load_balancer network + hcloud_load_balancer_network: + network: "{{ hcloud_network_name }}" + load_balancer: "{{hcloud_load_balancer_name}}" + state: absent + register: result +- name: verify test absent load_balancer network + assert: + that: + - result is changed + +- name: test create load_balancer network with specified ip + hcloud_load_balancer_network: + network: "{{ hcloud_network_name }}" + load_balancer: "{{hcloud_load_balancer_name}}" + ip: "10.0.0.2" + state: present + register: load_balancerNetwork +- name: verify create load_balancer network with specified ip + assert: + that: + - load_balancerNetwork is changed + - load_balancerNetwork.hcloud_load_balancer_network.network == hcloud_network_name + - load_balancerNetwork.hcloud_load_balancer_network.load_balancer == hcloud_load_balancer_name + - load_balancerNetwork.hcloud_load_balancer_network.ip == "10.0.0.2" + +- name: cleanup create load_balancer network with specified ip + hcloud_load_balancer_network: + network: "{{ hcloud_network_name }}" + load_balancer: "{{hcloud_load_balancer_name}}" + state: absent + register: result +- name: verify cleanup create load_balancer network with specified ip + assert: + that: + - result is changed + +- name: cleanup load_balancer + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: absent + register: result +- name: verify cleanup load_balancer + assert: + that: + - result is success + +- name: cleanup subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "cloud" + network_zone: "eu-central" + state: absent + register: result +- name: verify cleanup subnetwork + assert: + that: + - result is changed + +- name: cleanup + hcloud_network: + name: "{{hcloud_network_name}}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/defaults/main.yml new file mode 100644 index 00000000..0876695b --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_load_balancer_name: "{{hcloud_prefix}}-load_balancer-target" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/tasks/main.yml new file mode 100644 index 00000000..101effc0 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_service/tasks/main.yml @@ -0,0 +1,112 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup load_balancer + hcloud_load_balancer: + name: "{{hcloud_load_balancer_name}}" + load_balancer_type: lb11 + state: present + location: "fsn1" + register: load_balancer +- name: verify setup load_balancer + assert: + that: + - load_balancer is success + +- name: test create load_balancer service with checkmode + hcloud_load_balancer_service: + load_balancer: "{{hcloud_load_balancer_name}}" + protocol: "http" + listen_port: 80 + state: present + register: result + check_mode: yes +- name: verify test create load_balancer service with checkmode + assert: + that: + - result is changed + +- name: test create load_balancer service + hcloud_load_balancer_service: + load_balancer: "{{hcloud_load_balancer_name}}" + protocol: "http" + listen_port: 80 + state: present + register: load_balancer_service +- name: verify create load_balancer service + assert: + that: + - load_balancer_service is changed + - load_balancer_service.hcloud_load_balancer_service.protocol == "http" + - load_balancer_service.hcloud_load_balancer_service.listen_port == 80 + - load_balancer_service.hcloud_load_balancer_service.destination_port == 80 + - load_balancer_service.hcloud_load_balancer_service.proxyprotocol is sameas false + +- name: test create load_balancer service idempotency + hcloud_load_balancer_service: + load_balancer: "{{hcloud_load_balancer_name}}" + protocol: "http" + listen_port: 80 + state: present + register: load_balancer_service +- name: verify create load_balancer service idempotency + assert: + that: + - load_balancer_service is not changed + +- name: test update load_balancer service + hcloud_load_balancer_service: + load_balancer: "{{hcloud_load_balancer_name}}" + protocol: "tcp" + listen_port: 80 + state: present + register: load_balancer_service +- name: verify create load_balancer service + assert: + that: + - load_balancer_service is changed + - load_balancer_service.hcloud_load_balancer_service.protocol == "tcp" + - load_balancer_service.hcloud_load_balancer_service.listen_port == 80 + - load_balancer_service.hcloud_load_balancer_service.destination_port == 80 + - load_balancer_service.hcloud_load_balancer_service.proxyprotocol is sameas false + +- name: test absent load_balancer service + hcloud_load_balancer_service: + load_balancer: "{{hcloud_load_balancer_name}}" + protocol: "http" + listen_port: 80 + state: absent + register: result +- name: verify test absent load_balancer service + assert: + that: + - result is changed + +- name: test create load_balancer service with http + hcloud_load_balancer_service: + load_balancer: "{{hcloud_load_balancer_name}}" + protocol: "http" + listen_port: 80 + http: + cookie_name: "Test" + sticky_sessions: yes + state: present + register: load_balancer_service +- name: verify create load_balancer service + assert: + that: + - load_balancer_service is changed + - load_balancer_service.hcloud_load_balancer_service.protocol == "http" + - load_balancer_service.hcloud_load_balancer_service.listen_port == 80 + - load_balancer_service.hcloud_load_balancer_service.destination_port == 80 + - load_balancer_service.hcloud_load_balancer_service.proxyprotocol is sameas false + +- name: cleanup load_balancer + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: absent + register: result +- name: verify cleanup load_balancer + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml new file mode 100644 index 00000000..bb38666b --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/defaults/main.yml @@ -0,0 +1,7 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_server_name: "{{hcloud_prefix}}-lb-target" +hcloud_load_balancer_name: "{{hcloud_prefix}}-load_balancer-target" +hcloud_testing_ip: "176.9.59.39" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/tasks/main.yml new file mode 100644 index 00000000..33756688 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_target/tasks/main.yml @@ -0,0 +1,129 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup server + hcloud_server: + name: "{{hcloud_server_name}}" + server_type: cx11 + image: ubuntu-20.04 + state: started + location: "fsn1" + register: server +- name: verify setup server + assert: + that: + - server is success + +- name: setup load_balancer + hcloud_load_balancer: + name: "{{hcloud_load_balancer_name}}" + load_balancer_type: lb11 + state: present + location: "fsn1" + register: load_balancer +- name: verify setup load_balancer + assert: + that: + - load_balancer is success + +- name: test create load_balancer target with checkmode + hcloud_load_balancer_target: + type: "server" + load_balancer: "{{hcloud_load_balancer_name}}" + server: "{{hcloud_server_name}}" + state: present + register: result + check_mode: yes +- name: verify test create load_balancer target with checkmode + assert: + that: + - result is changed + +- name: test create load_balancer target + hcloud_load_balancer_target: + type: "server" + load_balancer: "{{hcloud_load_balancer_name}}" + server: "{{hcloud_server_name}}" + state: present + register: load_balancer_target +- name: verify create load_balancer target + assert: + that: + - load_balancer_target is changed + - load_balancer_target.hcloud_load_balancer_target.type == "server" + - load_balancer_target.hcloud_load_balancer_target.server == hcloud_server_name + - load_balancer_target.hcloud_load_balancer_target.load_balancer == hcloud_load_balancer_name + +- name: test create load_balancer target idempotency + hcloud_load_balancer_target: + type: "server" + load_balancer: "{{hcloud_load_balancer_name}}" + server: "{{hcloud_server_name}}" + state: present + register: load_balancer_target +- name: verify create load_balancer target idempotency + assert: + that: + - load_balancer_target is not changed + +- name: test absent load_balancer target + hcloud_load_balancer_target: + type: "server" + load_balancer: "{{hcloud_load_balancer_name}}" + server: "{{hcloud_server_name}}" + state: absent + register: result +- name: verify test absent load_balancer target + assert: + that: + - result is changed + +- name: test create label_selector target + hcloud_load_balancer_target: + type: "label_selector" + load_balancer: "{{hcloud_load_balancer_name}}" + label_selector: "application=backend" + state: present + register: load_balancer_target +- name: verify create label_selector target + assert: + that: + - load_balancer_target is changed + - load_balancer_target.hcloud_load_balancer_target.type == "label_selector" + - load_balancer_target.hcloud_load_balancer_target.label_selector == "application=backend" + - load_balancer_target.hcloud_load_balancer_target.load_balancer == hcloud_load_balancer_name + +- name: test create ip target + hcloud_load_balancer_target: + type: "ip" + load_balancer: "{{hcloud_load_balancer_name}}" + ip: "{{hcloud_testing_ip}}" + state: present + register: load_balancer_target +- name: verify create ip target + assert: + that: + - load_balancer_target is changed + - load_balancer_target.hcloud_load_balancer_target.type == "ip" + - load_balancer_target.hcloud_load_balancer_target.ip == hcloud_testing_ip + - load_balancer_target.hcloud_load_balancer_target.load_balancer == hcloud_load_balancer_name + +- name: cleanup load_balancer + hcloud_load_balancer: + name: "{{ hcloud_load_balancer_name }}" + state: absent + register: result +- name: verify cleanup load_balancer + assert: + that: + - result is success + +- name: cleanup + hcloud_server: + name: "{{hcloud_server_name}}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/defaults/main.yml new file mode 100644 index 00000000..b7fd8631 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_load_balancer_type_name: "lb11" +hcloud_load_balancer_type_id: 1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml new file mode 100644 index 00000000..bcd805a8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_load_balancer_type_info/tasks/main.yml @@ -0,0 +1,38 @@ +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: test gather hcloud Load Balancer type infos + hcloud_load_balancer_type_info: + register: hcloud_load_balancer_types +- name: verify test gather hcloud Load Balancer type infos + assert: + that: + - hcloud_load_balancer_types.hcloud_load_balancer_type_info| list | count >= 1 + +- name: test gather hcloud Load Balancer type infos in check mode + hcloud_load_balancer_type_info: + check_mode: yes + register: hcloud_load_balancer_types + +- name: verify test gather hcloud Load Balancer type infos in check mode + assert: + that: + - hcloud_load_balancer_types.hcloud_load_balancer_type_info| list | count >= 1 + +- name: test gather hcloud Load Balancer type infos with name + hcloud_load_balancer_type_info: + name: "{{hcloud_load_balancer_type_name}}" + register: hcloud_load_balancer_types +- name: verify test gather hcloud Load Balancer type with name + assert: + that: + - hcloud_load_balancer_types.hcloud_load_balancer_type_info|selectattr('name','equalto','{{ hcloud_load_balancer_type_name }}') | list | count == 1 + +- name: test gather hcloud Load Balancer type infos with correct id + hcloud_load_balancer_type_info: + id: "{{hcloud_load_balancer_type_id}}" + register: hcloud_load_balancer_types +- name: verify test gather hcloud Load Balancer type with correct id + assert: + that: + - hcloud_load_balancer_types.hcloud_load_balancer_type_info|selectattr('name','equalto','{{ hcloud_load_balancer_type_name }}') | list | count == 1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/defaults/main.yml new file mode 100644 index 00000000..0d72a75c --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_location_name: "fsn1" +hcloud_location_id: 1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/tasks/main.yml new file mode 100644 index 00000000..e0ae5f17 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_location_info/tasks/main.yml @@ -0,0 +1,57 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: test gather hcloud location infos + hcloud_location_info: + register: hcloud_location + +- name: verify test gather hcloud location infos + assert: + that: + - hcloud_location.hcloud_location_info | list | count == 3 + +- name: test gather hcloud location infos in check mode + hcloud_location_info: + check_mode: yes + register: hcloud_location + +- name: verify test gather hcloud location infos in check mode + assert: + that: + - hcloud_location.hcloud_location_info | list | count == 3 + +- name: test gather hcloud location infos with correct name + hcloud_location_info: + name: "{{hcloud_location_name}}" + register: hcloud_location +- name: verify test gather hcloud location with correct name + assert: + that: + - hcloud_location.hcloud_location_info|selectattr('name','equalto','{{ hcloud_location_name }}') | list | count == 1 + +- name: test gather hcloud location infos with wrong name + hcloud_location_info: + name: "{{hcloud_location_name}}1" + register: hcloud_location +- name: verify test gather hcloud location with wrong name + assert: + that: + - hcloud_location.hcloud_location_info | list | count == 0 + +- name: test gather hcloud location infos with correct id + hcloud_location_info: + id: "{{hcloud_location_id}}" + register: hcloud_location +- name: verify test gather hcloud location with correct id + assert: + that: + - hcloud_location.hcloud_location_info|selectattr('name','equalto','{{ hcloud_location_name }}') | list | count == 1 + +- name: test gather hcloud location infos with wrong id + hcloud_location_info: + name: "4711" + register: hcloud_location +- name: verify test gather hcloud location with wrong id + assert: + that: + - hcloud_location.hcloud_location_info | list | count == 0 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/aliases new file mode 100644 index 00000000..4b3a9b36 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/aliases @@ -0,0 +1,3 @@ +cloud/hcloud +shippable/hcloud/group1 +disabled diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/defaults/main.yml new file mode 100644 index 00000000..ecfa6a73 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_network_name: "{{hcloud_prefix}}-integ" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/tasks/main.yml new file mode 100644 index 00000000..6c40e4e0 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network/tasks/main.yml @@ -0,0 +1,215 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup + hcloud_network: + name: "{{ hcloud_network_name }}" + state: absent + register: result +- name: verify setup + assert: + that: + - result is success + +- name: test missing ip_range parameter on create Network + hcloud_network: + name: "{{hcloud_network_name}}" + register: result + ignore_errors: yes +- name: verify fail missing ip_range parameter on create Network result + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: ip_range"' + +- name: test create Network with check mode + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/16" + register: result + check_mode: yes +- name: verify create Network with check mode result + assert: + that: + - result is changed + +- name: test create Network + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/16" + register: network +- name: verify test create Network result + assert: + that: + - network is changed + - network.hcloud_network.name == "{{hcloud_network_name}}" + - network.hcloud_network.ip_range == "10.0.0.0/16" + +- name: test create Network idempotence + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/16" + register: network +- name: verify test create network + assert: + that: + - network is not changed + +- name: test update Network label + hcloud_network: + name: "{{hcloud_network_name}}" + labels: + key: value + register: network +- name: verify test update Network label + assert: + that: + - network is changed + - network.hcloud_network.labels.key == "value" + +- name: test update Network label idempotency + hcloud_network: + name: "{{hcloud_network_name}}" + labels: + key: value + register: network +- name: verify test update Network label idempotency + assert: + that: + - network is not changed + +- name: test update Network ip range + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/8" + register: network +- name: verify test update Network ip range + assert: + that: + - network is changed + - network.hcloud_network.ip_range == "10.0.0.0/8" + +- name: test update Network ip range idempotency + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/8" + register: network +- name: verify test update Network ip range idempotency + assert: + that: + - network is not changed + +- name: test update Network delete protection + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/8" + delete_protection: true + register: network +- name: verify test update Network delete protection + assert: + that: + - network is changed + - network.hcloud_network.delete_protection is sameas true + +- name: test update Network delete protection idempotency + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/8" + delete_protection: true + register: network +- name: verify test update Network delete protection idempotency + assert: + that: + - network is not changed + - network.hcloud_network.delete_protection is sameas true + +- name: test Network without delete protection set to be idempotent + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/8" + register: network +- name: verify test Network without delete protection set to be idempotent + assert: + that: + - network is not changed + - network.hcloud_network.delete_protection is sameas true + +- name: test delete Network fails if it is protected + hcloud_network: + name: "{{hcloud_network_name}}" + state: absent + ignore_errors: yes + register: result +- name: verify delete Network + assert: + that: + - result is failed + - 'result.msg == "network deletion is protected"' + +- name: test update Network delete protection + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/8" + delete_protection: false + register: network +- name: verify test update Network delete protection + assert: + that: + - network is changed + - network.hcloud_network.delete_protection is sameas false + +- name: test delete Network + hcloud_network: + name: "{{hcloud_network_name}}" + state: absent + register: result +- name: verify delete Network + assert: + that: + - result is success + + +- name: test create Network with delete protection + hcloud_network: + name: "{{hcloud_network_name}}" + ip_range: "10.0.0.0/8" + delete_protection: true + register: network +- name: verify create Network with delete protection + assert: + that: + - network is changed + - network.hcloud_network.delete_protection is sameas true + +- name: test delete Network fails if it is protected + hcloud_network: + name: "{{hcloud_network_name}}" + state: absent + ignore_errors: yes + register: result +- name: verify delete Network + assert: + that: + - result is failed + - 'result.msg == "network deletion is protected"' + +- name: test update Network delete protection + hcloud_network: + name: "{{hcloud_network_name}}" + delete_protection: false + register: network +- name: verify test update Network delete protection + assert: + that: + - network is changed + - network.hcloud_network.delete_protection is sameas false + +- name: test delete Network + hcloud_network: + name: "{{hcloud_network_name}}" + state: absent + register: result +- name: verify delete Network + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/defaults/main.yml new file mode 100644 index 00000000..f8a5279f --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_network_name: "{{hcloud_prefix}}-integration" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/tasks/main.yml new file mode 100644 index 00000000..e7924a8d --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_network_info/tasks/main.yml @@ -0,0 +1,117 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- + +- name: setup ensure network is absent + hcloud_network: + name: "{{ hcloud_network_name }}" + state: absent + register: result + +- name: create network + hcloud_network: + name: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + labels: + key: value + register: main_network +- name: verify create network + assert: + that: + - main_network is changed + - main_network.hcloud_network.name == "{{ hcloud_network_name }}" + - main_network.hcloud_network.ip_range == "10.0.0.0/16" +- name: create subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + type: server + network_zone: eu-central + ip_range: "10.0.1.0/24" + register: main_subnetwork +- name: verify create subnetwork + assert: + that: + - main_subnetwork is changed + - main_subnetwork.hcloud_subnetwork.network == "{{ hcloud_network_name }}" +- name: create route + hcloud_route: + network: "{{ hcloud_network_name }}" + destination: "10.0.3.0/24" + gateway: "10.0.2.1" + register: main_route +- name: verify create route + assert: + that: + - main_route is changed + - main_route.hcloud_route.network == "{{ hcloud_network_name }}" + +- name: test gather hcloud network info in check mode + hcloud_network_info: + check_mode: yes + register: hcloud_network +- name: verify test gather hcloud network info in check mode + assert: + that: + - hcloud_network.hcloud_network_info | selectattr('name','equalto','{{ hcloud_network_name }}') | list | count >= 1 + + +- name: test gather hcloud network info with correct label selector + hcloud_network_info: + label_selector: "key=value" + register: hcloud_network +- name: verify test gather hcloud network with correct label selector + assert: + that: + - hcloud_network.hcloud_network_info | selectattr('name','equalto','{{ hcloud_network_name }}') | list | count >= 1 + +- name: test gather hcloud network info with wrong label selector + hcloud_network_info: + label_selector: "key!=value" + register: hcloud_network +- name: verify test gather hcloud network with wrong label selector + assert: + that: + - hcloud_network.hcloud_network_info | list | count == 0 + +- name: test gather hcloud network info with correct name + hcloud_network_info: + name: "{{hcloud_network_name}}" + register: hcloud_network +- name: verify test gather hcloud network with correct name + assert: + that: + - hcloud_network.hcloud_network_info | selectattr('name','equalto','{{ hcloud_network_name }}') | list | count == 1 + - hcloud_network.hcloud_network_info[0].subnetworks | list | count >= 1 + - hcloud_network.hcloud_network_info[0].routes | list | count >= 1 + +- name: test gather hcloud network info with wrong name + hcloud_network_info: + name: "{{hcloud_network_name}}1" + register: hcloud_network +- name: verify test gather hcloud network with wrong name + assert: + that: + - hcloud_network.hcloud_network_info | list | count == 0 + +- name: test gather hcloud network info with correct id + hcloud_network_info: + id: "{{main_network.hcloud_network.id}}" + register: hcloud_network +- name: verify test gather hcloud network with correct id + assert: + that: + - hcloud_network.hcloud_network_info | selectattr('name','equalto','{{ hcloud_network_name }}') | list | count == 1 + +- name: test gather hcloud network info with wrong id + hcloud_network_info: + name: "4711" + register: hcloud_network +- name: verify test gather hcloud network with wrong id + assert: + that: + - hcloud_network.hcloud_network_info | list | count == 0 + +- name: cleanup + hcloud_network: + name: "{{ hcloud_network_name }}" + state: absent diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/defaults/main.yml new file mode 100644 index 00000000..fb46d1e1 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_server_name: "{{hcloud_prefix}}-rdns" +hcloud_floating_ip_name: "{{hcloud_prefix}}-rdns" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/meta/main.yml new file mode 100644 index 00000000..67d54d73 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - ansible.netcommon + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/tasks/main.yml new file mode 100644 index 00000000..f34f1047 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_rdns/tasks/main.yml @@ -0,0 +1,140 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: cx11 + image: "ubuntu-18.04" + ssh_keys: + - ci@ansible.hetzner.cloud + state: present + register: setup +- name: verify setup + assert: + that: + - setup is success + +- name: test create Floating IP + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + type: ipv4 + home_location: "fsn1" + register: floatingIP +- name: verify test create Floating IP + assert: + that: + - floatingIP is success + +- name: test missing required parameter + hcloud_rdns: + state: present + register: result + ignore_errors: yes +- name: verify fail test missing required parameters + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: ip_address"' + +- name: test create rdns + hcloud_rdns: + server: "{{ hcloud_server_name }}" + ip_address: "{{ setup.hcloud_server.ipv6 | ansible.netcommon.ipaddr('next_usable') }}" + dns_ptr: "example.com" + state: present + register: rdns +- name: verify create rdns + assert: + that: + - rdns is changed + - rdns.hcloud_rdns.server == "{{ hcloud_server_name }}" + - rdns.hcloud_rdns.ip_address == "{{ setup.hcloud_server.ipv6 | ansible.netcommon.ipaddr('next_usable') }}" + - rdns.hcloud_rdns.dns_ptr == "example.com" + +- name: test create rdns idempotency + hcloud_rdns: + server: "{{ hcloud_server_name }}" + ip_address: "{{ setup.hcloud_server.ipv6 | ansible.netcommon.ipaddr('next_usable') }}" + dns_ptr: "example.com" + state: present + register: result +- name: verify create rdns idempotency + assert: + that: + - result is not changed + +- name: test absent rdns + hcloud_rdns: + server: "{{ hcloud_server_name }}" + ip_address: "{{ setup.hcloud_server.ipv6 | ansible.netcommon.ipaddr('next_usable') }}" + state: absent + register: result +- name: verify test absent rdns + assert: + that: + - result is changed + +- name: test update rdns + hcloud_rdns: + server: "{{ hcloud_server_name }}" + ip_address: "{{ setup.hcloud_server.ipv4_address }}" + dns_ptr: "example.com" + state: present + register: rdns +- name: verify update rdns + assert: + that: + - rdns is changed + - rdns.hcloud_rdns.server == "{{ hcloud_server_name }}" + - rdns.hcloud_rdns.ip_address == "{{ setup.hcloud_server.ipv4_address }}" + - rdns.hcloud_rdns.dns_ptr == "example.com" + +- name: test reset rdns + hcloud_rdns: + server: "{{ hcloud_server_name }}" + ip_address: "{{ setup.hcloud_server.ipv4_address }}" + state: present + register: rdns +- name: verify reset rdns + assert: + that: + - rdns is changed + - rdns.hcloud_rdns.server == "{{ hcloud_server_name }}" + - rdns.hcloud_rdns.ip_address == "{{ setup.hcloud_server.ipv4_address }}" + - rdns.hcloud_rdns.dns_ptr != "example.com" + +- name: test create rdns with floating IP + hcloud_rdns: + floating_ip: "{{ hcloud_floating_ip_name }}" + ip_address: "{{ floatingIP.hcloud_floating_ip.ip}}" + dns_ptr: "example.com" + state: present + register: rdns +- name: verify create rdns + assert: + that: + - rdns is changed + - rdns.hcloud_rdns.floating_ip == "{{ hcloud_floating_ip_name }}" + - rdns.hcloud_rdns.ip_address == "{{ floatingIP.hcloud_floating_ip.ip}}" + - rdns.hcloud_rdns.dns_ptr == "example.com" + +- name: cleanup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success + +- name: cleanup + hcloud_floating_ip: + name: "{{ hcloud_floating_ip_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/defaults/main.yml new file mode 100644 index 00000000..62156272 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_network_name: "{{hcloud_prefix}}-routes" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/meta/main.yml new file mode 100644 index 00000000..67d54d73 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - ansible.netcommon + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/tasks/main.yml new file mode 100644 index 00000000..7d816bf5 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_route/tasks/main.yml @@ -0,0 +1,99 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup + hcloud_network: + name: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/8" + state: present + register: network +- name: verify setup + assert: + that: + - network is success + +- name: test missing required parameters on create route + hcloud_route: + state: present + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create route + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: destination, gateway, network"' + +- name: test create route with checkmode + hcloud_route: + network: "{{ hcloud_network_name }}" + destination: "10.100.1.0/24" + gateway: "10.0.1.1" + state: present + register: result + check_mode: yes +- name: verify test create route with checkmode + assert: + that: + - result is changed + +- name: test create route + hcloud_route: + network: "{{ hcloud_network_name }}" + destination: "10.100.1.0/24" + gateway: "10.0.1.1" + state: present + register: route +- name: verify create route + assert: + that: + - route is changed + - route.hcloud_route.network == "{{ hcloud_network_name }}" + - route.hcloud_route.destination == "10.100.1.0/24" + - route.hcloud_route.gateway == "10.0.1.1" + +- name: test create route idempotency + hcloud_route: + network: "{{ hcloud_network_name }}" + destination: "10.100.1.0/24" + gateway: "10.0.1.1" + state: present + register: result +- name: verify create route idempotency + assert: + that: + - result is not changed + +- name: test fail create route with wrong gateway + hcloud_route: + network: "{{ hcloud_network_name }}" + destination: "10.100.1.0/24" + gateway: "10.0.1.2" + state: present + register: route + ignore_errors: yes +- name: verfiy fail create route with wrong gateway + assert: + that: + - route is failed + +- name: test absent route + hcloud_route: + network: "{{ hcloud_network_name }}" + destination: "10.100.1.0/24" + gateway: "10.0.1.1" + state: absent + register: result +- name: verify test absent route + assert: + that: + - result is changed + +- name: cleanup + hcloud_network: + name: "{{hcloud_network_name}}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/aliases new file mode 100644 index 00000000..18dc30b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/defaults/main.yml new file mode 100644 index 00000000..b9a9a8df --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_server_name: "{{hcloud_prefix}}-integration" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/main.yml new file mode 100644 index 00000000..f4464f18 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server/tasks/main.yml @@ -0,0 +1,648 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify setup + assert: + that: + - result is success +- name: test missing required parameters on create server + hcloud_server: + name: "{{ hcloud_server_name }}" + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create server + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: server_type, image"' + +- name: test create server with check mode + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: cx11 + image: ubuntu-18.04 + state: present + register: result + check_mode: yes +- name: test create server server + assert: + that: + - result is changed + +- name: test create server + hcloud_server: + name: "{{ hcloud_server_name}}" + server_type: cx11 + image: ubuntu-18.04 + state: started + register: main_server +- name: verify create server + assert: + that: + - main_server is changed + - main_server.hcloud_server.name == "{{ hcloud_server_name }}" + - main_server.hcloud_server.server_type == "cx11" + - main_server.hcloud_server.status == "running" + - main_server.root_password != "" + +- name: test create server idempotence + hcloud_server: + name: "{{ hcloud_server_name }}" + state: started + register: result +- name: verify create server idempotence + assert: + that: + - result is not changed + +- name: test stop server with check mode + hcloud_server: + name: "{{ hcloud_server_name }}" + state: stopped + register: result + check_mode: yes +- name: verify stop server with check mode + assert: + that: + - result is changed + - result.hcloud_server.status == "running" + +- name: test stop server + hcloud_server: + name: "{{ hcloud_server_name }}" + state: stopped + register: result +- name: verify stop server + assert: + that: + - result is changed + - result.hcloud_server.status == "off" + +- name: test start server with check mode + hcloud_server: + name: "{{ hcloud_server_name }}" + state: started + register: result + check_mode: true +- name: verify start server with check mode + assert: + that: + - result is changed + +- name: test start server + hcloud_server: + name: "{{ hcloud_server_name }}" + state: started + register: result +- name: verify start server + assert: + that: + - result is changed + - result.hcloud_server.status == "running" + +- name: test start server idempotence + hcloud_server: + name: "{{ hcloud_server_name }}" + state: started + register: result +- name: verify start server idempotence + assert: + that: + - result is not changed + - result.hcloud_server.status == "running" + +- name: test stop server by its id + hcloud_server: + id: "{{ main_server.hcloud_server.id }}" + state: stopped + register: result +- name: verify stop server by its id + assert: + that: + - result is changed + - result.hcloud_server.status == "off" + +- name: test resize server running without force + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: "cx21" + state: present + register: result + check_mode: true +- name: verify test resize server running without force + assert: + that: + - result is changed + - result.hcloud_server.server_type == "cx11" + +- name: test resize server with check mode + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: "cx21" + state: stopped + register: result + check_mode: true +- name: verify resize server with check mode + assert: + that: + - result is changed + +- name: test resize server without disk + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: "cx21" + state: stopped + register: result +- name: verify resize server without disk + assert: + that: + - result is changed + - result.hcloud_server.server_type == "cx21" + +- name: test resize server idempotence + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: "cx21" + state: stopped + register: result +- name: verify resize server idempotence + assert: + that: + - result is not changed + +- name: test resize server to smaller plan + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: "cx11" + state: stopped + register: result +- name: verify resize server to smaller plan + assert: + that: + - result is changed + - result.hcloud_server.server_type == "cx11" + +- name: test resize server with disk + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: "cx21" + upgrade_disk: true + state: stopped + register: result +- name: verify resize server with disk + assert: + that: + - result is changed + - result.hcloud_server.server_type == "cx21" + +- name: test enable backups with check mode + hcloud_server: + name: "{{ hcloud_server_name }}" + backups: true + state: stopped + register: result + check_mode: true +- name: verify enable backups with check mode + assert: + that: + - result is changed + +- name: test enable backups + hcloud_server: + name: "{{ hcloud_server_name }}" + backups: true + state: stopped + register: result +- name: verify enable backups + assert: + that: + - result is changed + - result.hcloud_server.backup_window != "" + +- name: test enable backups idempotence + hcloud_server: + name: "{{ hcloud_server_name }}" + backups: true + state: stopped + register: result +- name: verify enable backups idempotence + assert: + that: + - result is not changed + - result.hcloud_server.backup_window != "" + +- name: test rebuild server + hcloud_server: + name: "{{ hcloud_server_name }}" + image: ubuntu-18.04 + state: rebuild + register: result_after_test +- name: verify rebuild server + assert: + that: + - result_after_test is changed + - result.hcloud_server.id == result_after_test.hcloud_server.id + +- name: test rebuild server with check mode + hcloud_server: + name: "{{ hcloud_server_name }}" + image: ubuntu-18.04 + state: rebuild + register: result_after_test + check_mode: true +- name: verify rebuild server with check mode + assert: + that: + - result_after_test is changed + +- name: test update server protection booth protection arguments are required + hcloud_server: + name: "{{ hcloud_server_name }}" + delete_protection: true + state: present + register: result_after_test + ignore_errors: true +- name: verify update server protection booth protection arguments are required + assert: + that: + - result_after_test is failed + - 'result_after_test.msg == "parameters are required together: delete_protection, rebuild_protection"' + +- name: test update server protection fails if they are not the same + hcloud_server: + name: "{{ hcloud_server_name }}" + delete_protection: true + rebuild_protection: false + state: present + register: result_after_test + ignore_errors: true +- name: verify update server protection fails if they are not the same + assert: + that: + - result_after_test is failed + +- name: test update server protection + hcloud_server: + name: "{{ hcloud_server_name }}" + delete_protection: true + rebuild_protection: true + state: present + register: result_after_test + ignore_errors: true +- name: verify update server protection + assert: + that: + - result_after_test is changed + - result_after_test.hcloud_server.delete_protection is sameas true + - result_after_test.hcloud_server.rebuild_protection is sameas true + +- name: test server without protection set to be idempotent + hcloud_server: + name: "{{hcloud_server_name}}" + register: result_after_test +- name: verify test server without protection set to be idempotent + assert: + that: + - result_after_test is not changed + - result_after_test.hcloud_server.delete_protection is sameas true + - result_after_test.hcloud_server.rebuild_protection is sameas true + +- name: test delete server fails if it is protected + hcloud_server: + name: "{{hcloud_server_name}}" + state: absent + ignore_errors: yes + register: result +- name: verify delete server fails if it is protected + assert: + that: + - result is failed + - 'result.msg == "server deletion is protected"' + +- name: test rebuild server fails if it is protected + hcloud_server: + name: "{{hcloud_server_name}}" + image: ubuntu-18.04 + state: rebuild + ignore_errors: yes + register: result +- name: verify rebuild server fails if it is protected + assert: + that: + - result is failed + - 'result.msg == "server rebuild is protected"' + +- name: test remove server protection + hcloud_server: + name: "{{ hcloud_server_name }}" + delete_protection: false + rebuild_protection: false + state: present + register: result_after_test + ignore_errors: true +- name: verify remove server protection + assert: + that: + - result_after_test is changed + - result_after_test.hcloud_server.delete_protection is sameas false + - result_after_test.hcloud_server.rebuild_protection is sameas false + +- name: absent server + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify absent server + assert: + that: + - result is success + +- name: test create server with ssh key + hcloud_server: + name: "{{ hcloud_server_name}}" + server_type: cx11 + image: "ubuntu-18.04" + ssh_keys: + - ci@ansible.hetzner.cloud + state: started + register: main_server +- name: verify create server with ssh key + assert: + that: + - main_server is changed + - main_server.hcloud_server.name == "{{ hcloud_server_name }}" + - main_server.hcloud_server.server_type == "cx11" + - main_server.hcloud_server.status == "running" + - main_server.root_password != "" + +- name: absent server + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify absent server + assert: + that: + - result is success + +- name: test create server with rescue_mode + hcloud_server: + name: "{{ hcloud_server_name}}" + server_type: cx11 + image: "ubuntu-18.04" + ssh_keys: + - ci@ansible.hetzner.cloud + rescue_mode: "linux64" + state: started + register: main_server +- name: verify create server with rescue_mode + assert: + that: + - main_server is changed + - main_server.hcloud_server.name == "{{ hcloud_server_name }}" + - main_server.hcloud_server.server_type == "cx11" + - main_server.hcloud_server.status == "running" + - main_server.root_password != "" + - main_server.hcloud_server.rescue_enabled is sameas true + +- name: absent server + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify absent server + assert: + that: + - result is success + +- name: setup server + hcloud_server: + name: "{{ hcloud_server_name}}" + server_type: cx11 + image: ubuntu-18.04 + state: started + register: main_server +- name: verify setup server + assert: + that: + - main_server is changed + - main_server.hcloud_server.name == "{{ hcloud_server_name }}" + - main_server.hcloud_server.server_type == "cx11" + - main_server.hcloud_server.status == "running" + - main_server.root_password != "" + +- name: test activate rescue mode with check_mode + hcloud_server: + name: "{{ hcloud_server_name }}" + rescue_mode: "linux64" + ssh_keys: + - ci@ansible.hetzner.cloud + state: present + register: main_server + check_mode: true +- name: verify activate rescue mode + assert: + that: + - main_server is changed + +- name: test activate rescue mode + hcloud_server: + name: "{{ hcloud_server_name }}" + rescue_mode: "linux64" + ssh_keys: + - ci@ansible.hetzner.cloud + state: present + register: main_server +- name: verify activate rescue mode + assert: + that: + - main_server is changed + - main_server.hcloud_server.rescue_enabled is sameas true + +- name: test disable rescue mode + hcloud_server: + name: "{{ hcloud_server_name }}" + ssh_keys: + - ci@ansible.hetzner.cloud + state: present + register: main_server +- name: verify activate rescue mode + assert: + that: + - main_server is changed + - main_server.hcloud_server.rescue_enabled is sameas false + +- name: test activate rescue mode without ssh keys + hcloud_server: + name: "{{ hcloud_server_name }}" + rescue_mode: "linux64" + state: present + register: main_server +- name: verify activate rescue mode without ssh keys + assert: + that: + - main_server is changed + - main_server.hcloud_server.rescue_enabled is sameas true + +- name: cleanup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success + +- name: test create server with labels + hcloud_server: + name: "{{ hcloud_server_name}}" + server_type: cx11 + image: "ubuntu-18.04" + ssh_keys: + - ci@ansible.hetzner.cloud + labels: + key: value + mylabel: "val123" + state: started + register: main_server +- name: verify create server with labels + assert: + that: + - main_server is changed + - main_server.hcloud_server.labels.key == "value" + - main_server.hcloud_server.labels.mylabel == "val123" + +- name: test update server with labels + hcloud_server: + name: "{{ hcloud_server_name}}" + server_type: cx11 + image: "ubuntu-18.04" + ssh_keys: + - ci@ansible.hetzner.cloud + labels: + key: other + mylabel: "val123" + state: started + register: main_server +- name: verify update server with labels + assert: + that: + - main_server is changed + - main_server.hcloud_server.labels.key == "other" + - main_server.hcloud_server.labels.mylabel == "val123" + +- name: test update server with labels in other order + hcloud_server: + name: "{{ hcloud_server_name}}" + server_type: cx11 + image: "ubuntu-18.04" + ssh_keys: + - ci@ansible.hetzner.cloud + labels: + mylabel: "val123" + key: other + state: started + register: main_server +- name: verify update server with labels in other order + assert: + that: + - main_server is not changed + +- name: cleanup with labels + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success + +- name: test create server with enabled backups + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: cpx11 + backups: true + image: "ubuntu-18.04" + ssh_keys: + - ci@ansible.hetzner.cloud + state: present + register: result +- name: verify enable backups + assert: + that: + - result is changed + - result.hcloud_server.backup_window != "" + +- name: test create server with enabled backups + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success + +- name: test create server with protection + hcloud_server: + name: "{{ hcloud_server_name }}" + delete_protection: true + rebuild_protection: true + server_type: cpx11 + image: "ubuntu-20.04" + ssh_keys: + - ci@ansible.hetzner.cloud + state: present + register: result_after_test + ignore_errors: true +- name: verify create server with protection + assert: + that: + - result_after_test is changed + - result_after_test.hcloud_server.delete_protection is sameas true + - result_after_test.hcloud_server.rebuild_protection is sameas true + + +- name: test delete server fails if it is protected + hcloud_server: + name: "{{hcloud_server_name}}" + state: absent + ignore_errors: yes + register: result +- name: verify delete server fails if it is protected + assert: + that: + - result is failed + - 'result.msg == "server deletion is protected"' + +- name: remove protection from server + hcloud_server: + name: "{{ hcloud_server_name }}" + delete_protection: false + rebuild_protection: false + state: present + register: result_after_test + ignore_errors: true +- name: verify update server protection + assert: + that: + - result_after_test is changed + - result_after_test.hcloud_server.delete_protection is sameas false + - result_after_test.hcloud_server.rebuild_protection is sameas false + +- name: cleanup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/defaults/main.yml new file mode 100644 index 00000000..b9a9a8df --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_server_name: "{{hcloud_prefix}}-integration" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/tasks/main.yml new file mode 100644 index 00000000..92eac5cc --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_info/tasks/main.yml @@ -0,0 +1,97 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup ensure server is absent + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result + +- name: create server + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: cx11 + image: ubuntu-18.04 + state: started + labels: + key: value + register: main_server +- name: verify create server + assert: + that: + - main_server is changed + - main_server.hcloud_server.name == "{{ hcloud_server_name }}" + - main_server.hcloud_server.server_type == "cx11" + - main_server.hcloud_server.status == "running" + - main_server.root_password != "" + + +- name: test gather hcloud server infos in check mode + hcloud_server_info: + register: hcloud_server + check_mode: yes + +- name: verify test gather hcloud server infos in check mode + assert: + that: + - hcloud_server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1 + + +- name: test gather hcloud server infos with correct label selector + hcloud_server_info: + label_selector: "key=value" + register: hcloud_server +- name: verify test gather hcloud server infos with correct label selector + assert: + that: + - hcloud_server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1 + +- name: test gather hcloud server infos with wrong label selector + hcloud_server_info: + label_selector: "key!=value" + register: hcloud_server +- name: verify test gather hcloud server infos with wrong label selector + assert: + that: + - hcloud_server.hcloud_server_info | list | count == 0 + +- name: test gather hcloud server infos with correct name + hcloud_server_info: + name: "{{hcloud_server_name}}" + register: hcloud_server +- name: verify test gather hcloud server infos with correct name + assert: + that: + - hcloud_server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1 + +- name: test gather hcloud server infos with wrong name + hcloud_server_info: + name: "{{hcloud_server_name}}1" + register: hcloud_server +- name: verify test gather hcloud server infos with wrong name + assert: + that: + - hcloud_server.hcloud_server_info | list | count == 0 + +- name: test gather hcloud server infos with correct id + hcloud_server_info: + id: "{{main_server.hcloud_server.id}}" + register: hcloud_server +- name: verify test gather hcloud server infos with correct id + assert: + that: + - hcloud_server.hcloud_server_info|selectattr('name','equalto','{{ hcloud_server_name }}') | list | count == 1 + +- name: test gather hcloud server infos with wrong id + hcloud_server_info: + name: "4711" + register: hcloud_server +- name: verify test gather hcloud server infos with wrong id + assert: + that: + - hcloud_server.hcloud_server_info | list | count == 0 + +- name: cleanup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/aliases new file mode 100644 index 00000000..7f17468b --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/aliases @@ -0,0 +1,3 @@ +cloud/hcloud +shippable/hcloud/group2 +disabled diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/defaults/main.yml new file mode 100644 index 00000000..1d62e5dc --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_network_name: "{{hcloud_prefix}}-server-network" +hcloud_server_name: "{{hcloud_prefix}}-server-network" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/tasks/main.yml new file mode 100644 index 00000000..754018a6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_network/tasks/main.yml @@ -0,0 +1,222 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup network + hcloud_network: + name: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/8" + state: present + register: network +- name: verify setup network + assert: + that: + - network is success + +- name: setup subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "server" + network_zone: "eu-central" + state: present + register: subnetwork +- name: verify subnetwork + assert: + that: + - subnetwork is success + +- name: setup server + hcloud_server: + name: "{{hcloud_server_name}}" + server_type: cx11 + image: ubuntu-18.04 + state: started + location: "fsn1" + register: server +- name: verify setup server + assert: + that: + - server is success + +- name: test missing required parameters on create server network + hcloud_server_network: + state: present + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create server network + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: network, server"' + +- name: test create server network with checkmode + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + state: present + register: result + check_mode: yes +- name: verify test create server network with checkmode + assert: + that: + - result is changed + +- name: test create server network + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + state: present + register: serverNetwork +- name: verify create server network + assert: + that: + - serverNetwork is changed + - serverNetwork.hcloud_server_network.network == hcloud_network_name + - serverNetwork.hcloud_server_network.server == hcloud_server_name + +- name: test create server network idempotency + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + state: present + register: serverNetwork +- name: verify create server network idempotency + assert: + that: + - serverNetwork is not changed + +- name: test absent server network + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + state: absent + register: result +- name: verify test absent server network + assert: + that: + - result is changed + +- name: test create server network with specified ip + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + ip: "10.0.0.2" + state: present + register: serverNetwork +- name: verify create server network with specified ip + assert: + that: + - serverNetwork is changed + - serverNetwork.hcloud_server_network.network == hcloud_network_name + - serverNetwork.hcloud_server_network.server == hcloud_server_name + - serverNetwork.hcloud_server_network.ip == "10.0.0.2" + +- name: cleanup create server network with specified ip + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + state: absent + register: result +- name: verify cleanup create server network with specified ip + assert: + that: + - result is changed + +- name: test create server network with alias ips + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + ip: "10.0.0.2" + alias_ips: + - "10.0.1.2" + - "10.0.2.3" + state: present + register: serverNetwork +- name: verify create server network with alias ips + assert: + that: + - serverNetwork is changed + - serverNetwork.hcloud_server_network.network == hcloud_network_name + - serverNetwork.hcloud_server_network.server == hcloud_server_name + - serverNetwork.hcloud_server_network.ip == "10.0.0.2" + - 'serverNetwork.hcloud_server_network.alias_ips[0] == "10.0.2.3"' + - 'serverNetwork.hcloud_server_network.alias_ips[1] == "10.0.1.2"' + +- name: test update server network with alias ips + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + ip: "10.0.0.2" + alias_ips: + - "10.0.2.3" + - "10.0.3.1" + state: present + register: serverNetwork +- name: verify create server network with alias ips + assert: + that: + - serverNetwork is changed + - serverNetwork.hcloud_server_network.network == hcloud_network_name + - serverNetwork.hcloud_server_network.server == hcloud_server_name + - serverNetwork.hcloud_server_network.ip == "10.0.0.2" + - 'serverNetwork.hcloud_server_network.alias_ips[0] == "10.0.2.3"' + - 'serverNetwork.hcloud_server_network.alias_ips[1] == "10.0.3.1"' + +- name: test update server network with alias ips idempotency + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + ip: "10.0.0.2" + alias_ips: + - "10.0.2.3" + - "10.0.3.1" + state: present + register: serverNetwork +- name: verify create server network with alias ips idempotency + assert: + that: + - serverNetwork is not changed + +- name: cleanup create server network with alias ips + hcloud_server_network: + network: "{{ hcloud_network_name }}" + server: "{{hcloud_server_name}}" + state: absent + register: result +- name: verify cleanup create server network with alias ips + assert: + that: + - result is changed + +- name: cleanup server + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup server + assert: + that: + - result is success + +- name: cleanup subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "server" + network_zone: "eu-central" + state: absent + register: result +- name: verify cleanup subnetwork + assert: + that: + - result is changed + +- name: cleanup + hcloud_network: + name: "{{hcloud_network_name}}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/defaults/main.yml new file mode 100644 index 00000000..05502aa9 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_server_type_name: "cx11" +hcloud_server_type_id: 1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/tasks/main.yml new file mode 100644 index 00000000..3c1fce8c --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_server_type_info/tasks/main.yml @@ -0,0 +1,38 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: test gather hcloud server type infos + hcloud_server_type_info: + register: hcloud_server_types +- name: verify test gather hcloud server type infos + assert: + that: + - hcloud_server_types.hcloud_server_type_info| list | count > 2 + +- name: test gather hcloud server type infos in check mode + hcloud_server_type_info: + check_mode: yes + register: hcloud_server_types + +- name: verify test gather hcloud server type infos in check mode + assert: + that: + - hcloud_server_types.hcloud_server_type_info| list | count > 2 + +- name: test gather hcloud server type infos with name + hcloud_server_type_info: + name: "{{hcloud_server_type_name}}" + register: hcloud_server_types +- name: verify test gather hcloud server type with name + assert: + that: + - hcloud_server_types.hcloud_server_type_info|selectattr('name','equalto','{{ hcloud_server_type_name }}') | list | count == 1 + +- name: test gather hcloud server type infos with correct id + hcloud_server_type_info: + id: "{{hcloud_server_type_id}}" + register: hcloud_server_types +- name: verify test gather hcloud server type with correct id + assert: + that: + - hcloud_server_types.hcloud_server_type_info|selectattr('name','equalto','{{ hcloud_server_type_name }}') | list | count == 1 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/defaults/main.yml new file mode 100644 index 00000000..666d3346 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/defaults/main.yml @@ -0,0 +1,8 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_server_name: "{{hcloud_prefix}}-integration" +hcloud_ssh_key_name: "{{hcloud_prefix}}-integration" +hcloud_ssh_key_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDnaTPfKaX1QKcRLOfr34buVLh5FhJAThI9NYB0xNdXsMd4Y0zLyyCQzHbx4eWCVZxym/s6csWSeLaAhO1GOHeAw3hQFMqf1oTBx6Y8g0pKpeotKPa/PDSUzdZF9Lc+DadtpQd8kFVHAu1Kd3zoEUnk1u6kP7I4qu4Z/6F9qBDF+M3aobiPVxdS7GwaVRW3nZu+FcQDLiBiNOjuRDyjHcDfEUkoh2SOu25RrFtGPzFu5mGmBJwotKpWAocLGfHzyn/fAHxgw3jKZVH/t+XWQFnl82Ie8yE3Z1EZ7oDkNRqFQT9AdXEQOLycTTYTQMJZpgeFTv3sAo6lPRCusiFmmLcf ci@ansible.hetzner.cloud" +hcloud_ssh_key_fingerprint: "56:89:c4:d6:a7:4a:79:82:f4:c2:58:9c:e1:d2:2d:4e" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/meta/main.yml new file mode 100644 index 00000000..5dcc0725 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/meta/main.yml @@ -0,0 +1,5 @@ +dependencies: + - setup_sshkey +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/tasks/main.yml new file mode 100644 index 00000000..baaadd4d --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key/tasks/main.yml @@ -0,0 +1,144 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: test missing required parameters on create ssh_key + hcloud_ssh_key: + name: "{{ hcloud_ssh_key_name }}" + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create ssh_key + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: public_key"' + +- name: test create ssh key with check mode + hcloud_ssh_key: + name: "{{ hcloud_ssh_key_name }}" + public_key: "{{ key_material }}" + register: result + check_mode: yes +- name: test create ssh key with check mode + assert: + that: + - result is changed + +- name: test create ssh key + hcloud_ssh_key: + name: "{{ hcloud_ssh_key_name }}" + public_key: "{{ key_material }}" + labels: + key: value + my-label: label + register: sshKey +- name: verify create ssh key + assert: + that: + - sshKey is changed + - sshKey.hcloud_ssh_key.name == "{{ hcloud_ssh_key_name }}" + - sshKey.hcloud_ssh_key.public_key == "{{ key_material }}" + - sshKey.hcloud_ssh_key.labels.key == "value" + +- name: test create ssh key idempotence + hcloud_ssh_key: + name: "{{ hcloud_ssh_key_name }}" + public_key: "{{ key_material }}" + register: result +- name: verify create ssh key idempotence + assert: + that: + - result is not changed + +- name: test update ssh key with check mode + hcloud_ssh_key: + id: "{{ sshKey.hcloud_ssh_key.id }}" + name: "changed-{{ hcloud_ssh_key_name }}" + register: result + check_mode: yes +- name: test create ssh key with check mode + assert: + that: + - result is changed + +- name: test update ssh key + hcloud_ssh_key: + id: "{{ sshKey.hcloud_ssh_key.id }}" + name: "changed-{{ hcloud_ssh_key_name }}" + labels: + key: value + register: result +- name: test update ssh key + assert: + that: + - result is changed + - result.hcloud_ssh_key.name == "changed-{{ hcloud_ssh_key_name }}" + +- name: test update ssh key with same labels + hcloud_ssh_key: + id: "{{ sshKey.hcloud_ssh_key.id }}" + name: "changed-{{ hcloud_ssh_key_name }}" + labels: + key: value + register: result +- name: test update ssh key with same labels + assert: + that: + - result is not changed + +- name: test update ssh key with other labels + hcloud_ssh_key: + id: "{{ sshKey.hcloud_ssh_key.id }}" + name: "changed-{{ hcloud_ssh_key_name }}" + labels: + key: value + test: "val123" + register: result +- name: test update ssh key with other labels + assert: + that: + - result is changed + +- name: test rename ssh key + hcloud_ssh_key: + id: "{{ sshKey.hcloud_ssh_key.id }}" + name: "{{ hcloud_ssh_key_name }}" + register: result +- name: test rename ssh key + assert: + that: + - result is changed + - result.hcloud_ssh_key.name == "{{ hcloud_ssh_key_name }}" + +- name: test create server with ssh key + hcloud_server: + name: "{{ hcloud_server_name }}" + server_type: cx11 + image: "ubuntu-18.04" + ssh_keys: + - "{{ hcloud_ssh_key_name }}" + state: started + register: main_server +- name: verify create server with ssh key + assert: + that: + - main_server is changed + +- name: absent ssh key + hcloud_ssh_key: + id: "{{ sshKey.hcloud_ssh_key.id }}" + state: absent + register: result +- name: verify absent server + assert: + that: + - result is success + +- name: cleanup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/defaults/main.yml new file mode 100644 index 00000000..06c1471a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_ssh_key_name: "{{hcloud_prefix}}-ssh_key_facts" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/meta/main.yml new file mode 100644 index 00000000..5dcc0725 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/meta/main.yml @@ -0,0 +1,5 @@ +dependencies: + - setup_sshkey +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml new file mode 100644 index 00000000..87cbd262 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_ssh_key_info/tasks/main.yml @@ -0,0 +1,68 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- + +- name: setup ensure ssh key is absent + hcloud_ssh_key: + name: "{{ hcloud_ssh_key_name }}" + state: absent + register: result + +- name: setup test ssh_key + hcloud_ssh_key: + name: "{{hcloud_ssh_key_name}}" + public_key: "{{ key_material }}" + labels: + key: value + register: result +- name: verify create test ssh_key + assert: + that: + - result is changed + - result.hcloud_ssh_key.public_key == "{{ key_material }}" + +- name: test gather hcloud ssh key infos in check mode + hcloud_ssh_key_info: + register: hcloud_ssh_key + check_mode: yes +- name: verify test gather hcloud ssh key infos in check mode + assert: + that: + - hcloud_ssh_key.hcloud_ssh_key_info| list | count >= 1 + +- name: test gather hcloud ssh key infos + hcloud_ssh_key_info: + register: hcloud_ssh_key + check_mode: yes +- name: verify test gather hcloud ssh key infos + assert: + that: + - hcloud_ssh_key.hcloud_ssh_key_info| list | count >= 1 + +- name: test gather hcloud ssh key infos with correct label selector + hcloud_ssh_key_info: + label_selector: "key=value" + register: hcloud_ssh_key +- name: verify test gather hcloud ssh key infos with correct label selector + assert: + that: + - hcloud_ssh_key.hcloud_ssh_key_info|selectattr('name','equalto','{{ hcloud_ssh_key_name }}') | list | count == 1 + +- name: test gather hcloud ssh key infos with wrong label selector + hcloud_ssh_key_info: + label_selector: "key!=value" + register: hcloud_ssh_key +- name: verify test gather hcloud ssh key infos with wrong label selector + assert: + that: + - hcloud_ssh_key.hcloud_ssh_key_info | list | count == 0 + +- name: cleanup + hcloud_ssh_key: + name: "{{hcloud_ssh_key_name}}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/aliases new file mode 100644 index 00000000..af1d98c3 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group3 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/defaults/main.yml new file mode 100644 index 00000000..51a123db --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_network_name: "{{hcloud_prefix}}-subnet" +hetzner_vswitch_id: 15311 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/tasks/main.yml new file mode 100644 index 00000000..0453f9d1 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_subnetwork/tasks/main.yml @@ -0,0 +1,125 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup + hcloud_network: + name: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/8" + state: present + register: network +- name: verify setup + assert: + that: + - network is success + +- name: test missing required parameters on create route + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + state: present + register: result + ignore_errors: yes +- name: verify fail test missing required parameters on create route + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: ip_range, network_zone, type"' + +- name: test create subnetwork with checkmode + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "server" + network_zone: "eu-central" + state: present + register: result + check_mode: yes +- name: verify test create subnetwork with checkmode + assert: + that: + - result is changed + +- name: test create subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "cloud" + network_zone: "eu-central" + state: present + register: subnet +- name: verify create subnetwork + assert: + that: + - subnet is changed + - subnet.hcloud_subnetwork.network == "{{ hcloud_network_name }}" + - subnet.hcloud_subnetwork.ip_range == "10.0.0.0/16" + - subnet.hcloud_subnetwork.type == "cloud" + - subnet.hcloud_subnetwork.network_zone == "eu-central" + +- name: test create subnetwork idempotency + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "cloud" + network_zone: "eu-central" + state: present + register: result +- name: verify create subnetwork idempotency + assert: + that: + - result is not changed + +- name: test absent subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "cloud" + network_zone: "eu-central" + state: absent + register: result +- name: verify test absent subnetwork + assert: + that: + - result is changed + +- name: test vswitch subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "vswitch" + network_zone: "eu-central" + vswitch_id: "{{ hetzner_vswitch_id }}" + state: present + register: subnet +- name: verify test vswitch subnetwork + assert: + that: + - subnet is changed + - subnet.hcloud_subnetwork.network == "{{ hcloud_network_name }}" + - subnet.hcloud_subnetwork.ip_range == "10.0.0.0/16" + - subnet.hcloud_subnetwork.type == "vswitch" + - subnet.hcloud_subnetwork.network_zone == "eu-central" + - subnet.hcloud_subnetwork.vswitch_id == hetzner_vswitch_id + +- name: test absent subnetwork + hcloud_subnetwork: + network: "{{ hcloud_network_name }}" + ip_range: "10.0.0.0/16" + type: "vswitch" + network_zone: "eu-central" + vswitch_id: "{{ hetzner_vswitch_id }}" + state: absent + register: subnet +- name: verify test absent subnetwork + assert: + that: + - result is changed + +- name: cleanup + hcloud_network: + name: "{{hcloud_network_name}}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/defaults/main.yml new file mode 100644 index 00000000..a8f03b4e --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/defaults/main.yml @@ -0,0 +1,6 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_volume_name: "{{hcloud_prefix}}-integ" +hcloud_server_name: "{{hcloud_prefix}}-volume-server" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/tasks/main.yml new file mode 100644 index 00000000..f763a52f --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume/tasks/main.yml @@ -0,0 +1,289 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup server + hcloud_server: + name: "{{hcloud_server_name}}" + server_type: cx11 + image: ubuntu-18.04 + state: started + location: "fsn1" + register: vol_server +- name: verify setup server + assert: + that: + - vol_server is changed + +- name: test missing size parameter on create Volume + hcloud_volume: + name: "{{hcloud_volume_name}}" + server: "{{hcloud_server_name}}" + register: result + ignore_errors: yes +- name: verify fail test missing size parameter on create Volume + assert: + that: + - result is failed + - 'result.msg == "missing required arguments: size"' + +- name: test create Volume with check mode + hcloud_volume: + name: "{{hcloud_volume_name}}" + size: 10 + location: "fsn1" + register: result + check_mode: yes +- name: verify create Volume with check mode result + assert: + that: + - result is changed + +- name: test create Volume + hcloud_volume: + name: "{{hcloud_volume_name}}" + size: 10 + location: "fsn1" + register: volume +- name: verify test create Volume + assert: + that: + - volume is changed + - volume.hcloud_volume.name == "{{hcloud_volume_name}}" + - volume.hcloud_volume.location == "fsn1" + - volume.hcloud_volume.size == 10 + - volume.hcloud_volume.server != "{{hcloud_server_name}}" + - volume.hcloud_volume.linux_device is defined + +- name: test create Volume idempotence + hcloud_volume: + name: "{{hcloud_volume_name}}" + size: 10 + location: "fsn1" + register: volume +- name: verify test create Volume + assert: + that: + - volume is not changed + +- name: test attach Volume with checkmode + hcloud_volume: + name: "{{hcloud_volume_name}}" + server: "{{hcloud_server_name}}" + check_mode: yes + register: volume +- name: verify test attach Volume with checkmode + assert: + that: + - volume is changed + - volume.hcloud_volume.server != "{{hcloud_server_name}}" + +- name: test attach Volume + hcloud_volume: + name: "{{hcloud_volume_name}}" + server: "{{hcloud_server_name}}" + register: volume +- name: verify attach volume + assert: + that: + - volume is changed + - volume.hcloud_volume.server == "{{hcloud_server_name}}" + +- name: test attach Volume idempotence + hcloud_volume: + name: "{{hcloud_volume_name}}" + server: "{{hcloud_server_name}}" + register: volume +- name: verify attach Volume idempotence + assert: + that: + - volume is not changed + - volume.hcloud_volume.server == "{{hcloud_server_name}}" + +- name: test detach Volume with checkmode + hcloud_volume: + name: "{{hcloud_volume_name}}" + check_mode: yes + register: volume +- name: verify detach Volume with checkmode + assert: + that: + - volume is changed + - volume.hcloud_volume.server == "{{hcloud_server_name}}" + +- name: test detach Volume + hcloud_volume: + name: "{{hcloud_volume_name}}" + register: volume +- name: verify detach volume + assert: + that: + - volume is changed + - volume.hcloud_volume.location == "fsn1" + - volume.hcloud_volume.server != "{{hcloud_server_name}}" + +- name: test update Volume label + hcloud_volume: + name: "{{hcloud_volume_name}}" + labels: + key: value + register: volume +- name: verify test update Volume label + assert: + that: + - volume is changed + - volume.hcloud_volume.labels.key == "value" + +- name: test update Volume label with the same label + hcloud_volume: + name: "{{hcloud_volume_name}}" + labels: + key: value + register: volume +- name: verify test update Volume lable with the same label + assert: + that: + - volume is not changed + +- name: test increase Volume size + hcloud_volume: + name: "{{hcloud_volume_name}}" + size: 11 + register: volume +- name: verify test increase Volume size + assert: + that: + - volume is changed + - volume.hcloud_volume.size == 11 + +- name: test decreace Volume size + hcloud_volume: + name: "{{hcloud_volume_name}}" + size: 10 + register: volume +- name: verify test decreace Volume size + assert: + that: + - volume is not changed + - volume.hcloud_volume.size == 11 + +- name: test update Volume delete protection + hcloud_volume: + name: "{{hcloud_volume_name}}" + delete_protection: true + register: volume +- name: verify test update Volume delete protection + assert: + that: + - volume is changed + - volume.hcloud_volume.delete_protection is sameas true + +- name: test update Volume delete protection idempotency + hcloud_volume: + name: "{{hcloud_volume_name}}" + delete_protection: true + register: volume +- name: verify test update Volume delete protection idempotency + assert: + that: + - volume is not changed + - volume.hcloud_volume.delete_protection is sameas true + +- name: test Volume without delete protection set to be idempotent + hcloud_volume: + name: "{{hcloud_volume_name}}" + register: volume +- name: verify test Volume without delete protection set to be idempotent + assert: + that: + - volume is not changed + - volume.hcloud_volume.delete_protection is sameas true + +- name: test delete Volume fails if it is protected + hcloud_volume: + name: "{{hcloud_volume_name}}" + state: absent + ignore_errors: yes + register: result +- name: verify delete Volume fails if it is protected + assert: + that: + - result is failed + - 'result.msg == "volume deletion is protected"' + +- name: test update Volume delete protection + hcloud_volume: + name: "{{hcloud_volume_name}}" + delete_protection: false + register: volume +- name: verify test update Volume delete protection + assert: + that: + - volume is changed + - volume.hcloud_volume.delete_protection is sameas false + +- name: test delete Volume + hcloud_volume: + name: "{{hcloud_volume_name}}" + state: absent + register: result +- name: verify delete Volume + assert: + that: + - result is success + + +- name: test create Volume with delete protection + hcloud_volume: + name: "{{hcloud_volume_name}}" + size: 10 + location: "fsn1" + delete_protection: true + register: volume +- name: verify create Volume with delete protection + assert: + that: + - volume is changed + - volume.hcloud_volume.delete_protection is sameas true + +- name: test delete Volume fails if it is protected + hcloud_volume: + name: "{{hcloud_volume_name}}" + state: absent + ignore_errors: yes + register: result +- name: verify delete Volume fails if it is protected + assert: + that: + - result is failed + - 'result.msg == "volume deletion is protected"' + +- name: test update Volume delete protection + hcloud_volume: + name: "{{hcloud_volume_name}}" + delete_protection: false + register: volume +- name: verify test update Volume delete protection + assert: + that: + - volume is changed + - volume.hcloud_volume.delete_protection is sameas false + +- name: test delete Volume + hcloud_volume: + name: "{{hcloud_volume_name}}" + state: absent + register: result +- name: verify delete Volume + assert: + that: + - result is success + +- name: cleanup + hcloud_server: + name: "{{ hcloud_server_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/aliases b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/aliases new file mode 100644 index 00000000..55ec821a --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/aliases @@ -0,0 +1,2 @@ +cloud/hcloud +shippable/hcloud/group2 diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/defaults/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/defaults/main.yml new file mode 100644 index 00000000..d308c950 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/defaults/main.yml @@ -0,0 +1,5 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +hcloud_prefix: "tests" +hcloud_volume_name: "{{hcloud_prefix}}-facts" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/meta/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/meta/main.yml new file mode 100644 index 00000000..407c9018 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/meta/main.yml @@ -0,0 +1,3 @@ +collections: + - community.general.ipfilter + - hetzner.cloud diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/tasks/main.yml new file mode 100644 index 00000000..ecea7ad3 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/hcloud_volume_info/tasks/main.yml @@ -0,0 +1,101 @@ +# Copyright: (c) 2019, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +--- +- name: setup ensure volume is absent + hcloud_volume: + name: "{{ hcloud_volume_name }}" + state: absent + register: result + +- name: setup volume + hcloud_volume: + name: "{{hcloud_volume_name}}" + size: 10 + location: "fsn1" + labels: + key: value + register: main_volume +- name: verify setup volume + assert: + that: + - main_volume is changed + +- name: test gather hcloud volume infos in check mode + hcloud_volume_info: + register: hcloud_volume + check_mode: yes + +- name: verify test gather hcloud volume infos in check mode + vars: + volume: "{{ hcloud_volume.hcloud_volume_info|selectattr('name','equalto',hcloud_volume_name) | first }}" + assert: + that: + - hcloud_volume.hcloud_volume_info|selectattr('name','equalto','{{ hcloud_volume_name }}') | list | count == 1 + - volume.name == "{{hcloud_volume_name}}" + - volume.location == "fsn1" + - volume.size == 10 + - volume.linux_device is defined + +- name: test gather hcloud volume infos with correct label selector + hcloud_volume_info: + label_selector: "key=value" + register: hcloud_volume +- name: verify test gather hcloud volume infos with correct label selector + assert: + that: + - hcloud_volume.hcloud_volume_info|selectattr('name','equalto','{{ hcloud_volume_name }}') | list | count == 1 + +- name: test gather hcloud volume infos with wrong label selector + hcloud_volume_info: + label_selector: "key!=value" + register: hcloud_volume +- name: verify test gather hcloud volume infos with wrong label selector + assert: + that: + - hcloud_volume.hcloud_volume_info | list | count == 0 + +- name: test gather hcloud volume infos with correct name + hcloud_volume_info: + name: "{{hcloud_volume_name}}" + register: hcloud_volume +- name: verify test gather hcloud volume infos with correct name + assert: + that: + - hcloud_volume.hcloud_volume_info|selectattr('name','equalto','{{ hcloud_volume_name }}') | list | count == 1 + +- name: test gather hcloud volume infos with wrong name + hcloud_volume_info: + name: "{{hcloud_volume_name}}1" + register: hcloud_volume +- name: verify test gather hcloud volume infos with wrong name + assert: + that: + - hcloud_volume.hcloud_volume_info | list | count == 0 + +- name: test gather hcloud volume facts with correct id + hcloud_volume_info: + id: "{{main_volume.hcloud_volume.id}}" + register: hcloud_volume +- name: verify test gather hcloud volume with correct id + assert: + that: + - hcloud_volume.hcloud_volume_info|selectattr('name','equalto','{{ hcloud_volume_name }}') | list | count == 1 + +- name: test gather hcloud volume infos with wrong id + hcloud_volume_info: + name: "4711" + register: hcloud_volume +- name: verify test gather hcloud volume infos with wrong id + assert: + that: + - hcloud_volume.hcloud_volume_info | list | count == 0 + +- name: cleanup + hcloud_volume: + name: "{{ hcloud_volume_name }}" + state: absent + register: result +- name: verify cleanup + assert: + that: + - result is success diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml new file mode 100644 index 00000000..27defe44 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_selfsigned_certificate/tasks/main.yml @@ -0,0 +1,27 @@ +# Copyright: (c) 2020, Hetzner Cloud GmbH <info@hetzner-cloud.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: create a cert temp file + tempfile: + state: file + register: certificate_example_com + tags: + - prepare +- name: create a key temp file + tempfile: + state: file + register: certificate_example_com_key + tags: + - prepare + - +- name: generate certificate + shell: openssl req -nodes -new -x509 -keyout {{ certificate_example_com_key.path }} -out {{ certificate_example_com.path }} -subj "/C=DE/ST=Munich/L=Bavaria/O=Dis/CN=www.example.com" + tags: + - prepare + +- name: set facts for future roles + set_fact: + certificate_example_com: "{{ lookup('file',certificate_example_com.path) }}" + certificate_example_com_key: "{{ lookup('file',certificate_example_com_key.path) }}" + tags: + - prepare diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_sshkey/tasks/main.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_sshkey/tasks/main.yml new file mode 100644 index 00000000..18c571b6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/integration/targets/setup_sshkey/tasks/main.yml @@ -0,0 +1,55 @@ +# (c) 2014, James Laska <jlaska@ansible.com> + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +- name: create a temp file + tempfile: + state: file + register: sshkey_file + tags: + - prepare + +- name: generate sshkey + shell: echo 'y' | ssh-keygen -P '' -f {{ sshkey_file.path }} + tags: + - prepare + +- name: create another temp file + tempfile: + state: file + register: another_sshkey_file + tags: + - prepare + +- name: generate another_sshkey + shell: echo 'y' | ssh-keygen -P '' -f {{ another_sshkey_file.path }} + tags: + - prepare + +- name: record fingerprint + shell: openssl rsa -in {{ sshkey_file.path }} -pubout -outform DER 2>/dev/null | openssl md5 -c + register: fingerprint + tags: + - prepare + +- name: set facts for future roles + set_fact: + sshkey: '{{ sshkey_file.path }}' + key_material: "{{ lookup('file', sshkey_file.path ~ '.pub') }}" + another_key_material: "{{ lookup('file', another_sshkey_file.path ~ '.pub') }}" + fingerprint: '{{ fingerprint.stdout.split()[1] }}' + tags: + - prepare diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/requirements.yml b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/requirements.yml new file mode 100644 index 00000000..6c49d0d9 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/requirements.yml @@ -0,0 +1,3 @@ +integration_tests_dependencies: +- community.general +- ansible.netcommon diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/sanity/requirements.txt b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/sanity/requirements.txt new file mode 100644 index 00000000..3e3a9669 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/sanity/requirements.txt @@ -0,0 +1,4 @@ +packaging # needed for update-bundled and changelog +sphinx ; python_version >= '3.5' # docs build requires python 3+ +sphinx-notfound-page ; python_version >= '3.5' # docs build requires python 3+ +straight.plugin ; python_version >= '3.5' # needed for hacking/build-ansible.py which will host changelog generation and requires python 3+ diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/gitlab.sh b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/gitlab.sh new file mode 100755 index 00000000..33c3af8e --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/gitlab.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args + +IFS='/:' read -ra args <<< "$1" + +ansible_version="${args[0]}" +script="${args[1]}" + +function join { + local IFS="$1"; + shift; + echo "$*"; +} + +test="$(join / "${args[@]:1}")" +command -v python +python -V + +function retry +{ + for repetition in 1 2 3; do + set +e + "$@" + result=$? + set -e + if [ ${result} == 0 ]; then + return ${result} + fi + echo "$@ -> ${result}" + done + echo "Command '$@' failed 3 times!" + exit -1 +} + +command -v pip +pip --version +pip list --disable-pip-version-check +if [ "${ansible_version}" == "devel" ]; then + retry pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check +else + retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check +fi +export ANSIBLE_COLLECTIONS_PATHS="${HOME}/.ansible" +SHIPPABLE_RESULT_DIR="$(pwd)/shippable" +TEST_DIR="${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/hetzner/hcloud" +rm -rf "${TEST_DIR}" +mkdir -p "${TEST_DIR}" +cp -r "." "${TEST_DIR}" +cd "${TEST_DIR}" + +# STAR: HACK install dependencies +retry ansible-galaxy -vvv collection install community.general +retry ansible-galaxy -vvv collection install ansible.netcommon +retry ansible-galaxy -vvv collection install community.internal_test_tools +retry pip install netaddr --disable-pip-version-check +retry pip install hcloud +retry pip install rstcheck +# END: HACK + +export PYTHONIOENCODING='utf-8' + +if [ "${JOB_TRIGGERED_BY_NAME:-}" == "nightly-trigger" ]; then + COMPLETE=yes +fi + + +if [ -n "${COMPLETE:-}" ]; then + # disable change detection triggered by setting the COMPLETE environment variable to a non-empty value + export CHANGED="" +elif [[ "${CI_COMMIT_MESSAGE}" =~ ci_complete ]]; then + # disable change detection triggered by having 'ci_complete' in the latest commit message + export CHANGED="" +else + # enable change detection (default behavior) + export CHANGED="" +fi + + +export UNSTABLE="--allow-unstable-changed" + +# remove empty core/extras module directories from PRs created prior to the repo-merge +find plugins -type d -empty -print -delete + +ansible-test env --dump --show --timeout "50" --color -v + +group="${args[1]}" +echo $test +if [[ "${test}" =~ hcloud ]]; then + group="${args[3]}" + bash tests/utils/gitlab/integration.sh "shippable/hcloud/group${group}/" +else + bash tests/utils/gitlab/sanity.sh "sanity/${group}" +fi diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/integration.sh b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/integration.sh new file mode 100755 index 00000000..2d660c88 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/integration.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +target="$1" + +HCLOUD_TOKEN=$(cat hcloud_token.txt) +changed_all_target="shippable/${cloud}/smoketest/" + +echo "[default] +hcloud_api_token=${HCLOUD_TOKEN} +" >> $(pwd)/tests/integration/cloud-config-hcloud.ini +# shellcheck disable=SC2086 +export SHIPPABLE="true" +export SHIPPABLE_BUILD_NUMBER="gl-$(cat prefix.txt)" +export SHIPPABLE_JOB_NUMBER="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 2 | head -n 1)" +ansible-test integration --color --local -vv "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/sanity.sh b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/sanity.sh new file mode 100755 index 00000000..1418edc0 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/gitlab/sanity.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +group="${args[1]}" + +if [ "${BASE_BRANCH:-}" ]; then + base_branch="origin/${BASE_BRANCH}" +else + base_branch="" +fi + +if [ "${group}" == "extra" ]; then + ../internal_test_tools/tools/run.py --color + exit +fi + +case "${group}" in + 1) options=(--skip-test pylint --skip-test ansible-doc --skip-test validate-modules) ;; + 2) options=( --test ansible-doc --test validate-modules) ;; + 3) options=(--test pylint plugins/modules/) ;; + 4) options=(--test pylint --exclude plugins/modules/) ;; +esac + +# allow collection migration sanity tests for groups 3 and 4 to pass without updating this script during migration +network_path="lib/ansible/modules/network/" + +if [ -d "${network_path}" ]; then + if [ "${group}" -eq 3 ]; then + options+=(--exclude "${network_path}") + elif [ "${group}" -eq 4 ]; then + options+=("${network_path}") + fi +fi + +pip install pycodestyle +pip install yamllint +pip install voluptuous +pip install pylint +# shellcheck disable=SC2086 +ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \ + --base-branch "${base_branch}" \ + --exclude shippable.yml --exclude tests/utils/ \ + "${options[@]}" --allow-disabled diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/check_matrix.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/check_matrix.py new file mode 100755 index 00000000..dfcca3e6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/check_matrix.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +"""Verify the currently executing Shippable test matrix matches the one defined in the "shippable.yml" file.""" +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import datetime +import json +import os +import re +import sys +import time + +try: + from typing import NoReturn +except ImportError: + NoReturn = None + +try: + # noinspection PyCompatibility + from urllib2 import urlopen # pylint: disable=ansible-bad-import-from +except ImportError: + # noinspection PyCompatibility + from urllib.request import urlopen + + +def main(): # type: () -> None + """Main entry point.""" + repo_full_name = os.environ['REPO_FULL_NAME'] + required_repo_full_name = 'ansible-collections/hetzner.hcloud' + + if repo_full_name != required_repo_full_name: + sys.stderr.write('Skipping matrix check on repo "%s" which is not "%s".\n' % (repo_full_name, required_repo_full_name)) + return + + with open('shippable.yml', 'rb') as yaml_file: + yaml = yaml_file.read().decode('utf-8').splitlines() + + defined_matrix = [match.group(1) for match in [re.search(r'^ *- env: T=(.*)$', line) for line in yaml] if match and match.group(1) != 'none'] + + if not defined_matrix: + fail('No matrix entries found in the "shippable.yml" file.', + 'Did you modify the "shippable.yml" file?') + + run_id = os.environ['SHIPPABLE_BUILD_ID'] + sleep = 1 + jobs = [] + + for attempts_remaining in range(4, -1, -1): + try: + jobs = json.loads(urlopen('https://api.shippable.com/jobs?runIds=%s' % run_id).read()) + + if not isinstance(jobs, list): + raise Exception('Shippable run %s data is not a list.' % run_id) + + break + except Exception as ex: + if not attempts_remaining: + fail('Unable to retrieve Shippable run %s matrix.' % run_id, + str(ex)) + + sys.stderr.write('Unable to retrieve Shippable run %s matrix: %s\n' % (run_id, ex)) + sys.stderr.write('Trying again in %d seconds...\n' % sleep) + time.sleep(sleep) + sleep *= 2 + + if len(jobs) != len(defined_matrix): + if len(jobs) == 1: + hint = '\n\nMake sure you do not use the "Rebuild with SSH" option.' + else: + hint = '' + + fail('Shippable run %s has %d jobs instead of the expected %d jobs.' % (run_id, len(jobs), len(defined_matrix)), + 'Try re-running the entire matrix.%s' % hint) + + actual_matrix = dict((job.get('jobNumber'), dict(tuple(line.split('=', 1)) for line in job.get('env', [])).get('T', '')) for job in jobs) + errors = [(job_number, test, actual_matrix.get(job_number)) for job_number, test in enumerate(defined_matrix, 1) if actual_matrix.get(job_number) != test] + + if len(errors): + error_summary = '\n'.join('Job %s expected "%s" but found "%s" instead.' % (job_number, expected, actual) for job_number, expected, actual in errors) + + fail('Shippable run %s has a job matrix mismatch.' % run_id, + 'Try re-running the entire matrix.\n\n%s' % error_summary) + + +def fail(message, output): # type: (str, str) -> NoReturn + # Include a leading newline to improve readability on Shippable "Tests" tab. + # Without this, the first line becomes indented. + output = '\n' + output.strip() + + timestamp = datetime.datetime.utcnow().replace(microsecond=0).isoformat() + + # hack to avoid requiring junit-xml, which isn't pre-installed on Shippable outside our test containers + xml = ''' +<?xml version="1.0" encoding="utf-8"?> +<testsuites disabled="0" errors="1" failures="0" tests="1" time="0.0"> +\t<testsuite disabled="0" errors="1" failures="0" file="None" log="None" name="ansible-test" skipped="0" tests="1" time="0" timestamp="%s" url="None"> +\t\t<testcase classname="timeout" name="timeout"> +\t\t\t<error message="%s" type="error">%s</error> +\t\t</testcase> +\t</testsuite> +</testsuites> +''' % (timestamp, message, output) + + path = 'shippable/testresults/check-matrix.xml' + dir_path = os.path.dirname(path) + + if not os.path.exists(dir_path): + os.makedirs(dir_path) + + with open(path, 'w') as junit_fd: + junit_fd.write(xml.lstrip()) + + sys.stderr.write(message + '\n') + sys.stderr.write(output + '\n') + + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/hcloud.sh b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/hcloud.sh new file mode 100755 index 00000000..da037e09 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/hcloud.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +cloud="${args[0]}" +python="${args[1]}" +group="${args[2]}" + +target="shippable/${cloud}/group${group}/" + +stage="${S:-prod}" + +changed_all_target="shippable/${cloud}/smoketest/" + +if ! ansible-test integration "${changed_all_target}" --list-targets > /dev/null 2>&1; then + # no smoketest tests are available for this cloud + changed_all_target="none" +fi + +if [ "${group}" == "1" ]; then + # only run smoketest tests for group1 + changed_all_mode="include" +else + # smoketest tests already covered by group1 + changed_all_mode="exclude" +fi + +# shellcheck disable=SC2086 +ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \ + --remote-terminate always --remote-stage "${stage}" \ + --docker --python "${python}" --changed-all-target "${changed_all_target}" --changed-all-mode "${changed_all_mode}" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/sanity.sh b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/sanity.sh new file mode 100755 index 00000000..1c297c58 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/sanity.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +group="${args[1]}" + +if [ "${BASE_BRANCH:-}" ]; then + base_branch="origin/${BASE_BRANCH}" +else + base_branch="" +fi + +if [ "${group}" == "extra" ]; then + pip install antsibull-changelog + python ../../community/internal_test_tools/tools/run.py --color + exit +fi + +case "${group}" in + 1) options=(--skip-test pylint --skip-test ansible-doc --skip-test validate-modules) ;; + 2) options=( --test ansible-doc --test validate-modules) ;; + 3) options=(--test pylint plugins/modules/) ;; + 4) options=(--test pylint --exclude plugins/modules/) ;; +esac + +# allow collection migration sanity tests for groups 3 and 4 to pass without updating this script during migration +network_path="lib/ansible/modules/network/" + +if [ -d "${network_path}" ]; then + if [ "${group}" -eq 3 ]; then + options+=(--exclude "${network_path}") + elif [ "${group}" -eq 4 ]; then + options+=("${network_path}") + fi +fi + +# shellcheck disable=SC2086 +ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \ + --docker --base-branch "${base_branch}" \ + --exclude shippable.yml --exclude tests/utils/ \ + "${options[@]}" --allow-disabled diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/shippable.sh b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/shippable.sh new file mode 100755 index 00000000..9303277f --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/shippable.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +ansible_version="${args[0]}" +script="${args[1]}" + +function join { + local IFS="$1"; + shift; + echo "$*"; +} + +test="$(join / "${args[@]:1}")" + +docker images ansible/ansible +docker images quay.io/ansible/* +docker ps + +for container in $(docker ps --format '{{.Image}} {{.ID}}' | grep -v '^drydock/' | sed 's/^.* //'); do + docker rm -f "${container}" || true # ignore errors +done + +docker ps + +if [ -d /home/shippable/cache/ ]; then + ls -la /home/shippable/cache/ +fi + +command -v python +python -V + +function retry +{ + for repetition in 1 2 3; do + set +e + "$@" + result=$? + set -e + if [ ${result} == 0 ]; then + return ${result} + fi + echo "$@ -> ${result}" + done + echo "Command '$@' failed 3 times!" + exit -1 +} + +command -v pip +pip --version +pip list --disable-pip-version-check +if [ "${ansible_version}" == "devel" ]; then + retry pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check +else + retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check +fi +export ANSIBLE_COLLECTIONS_PATHS="${HOME}/.ansible" +SHIPPABLE_RESULT_DIR="$(pwd)/shippable" +TEST_DIR="${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/hetzner/hcloud" +mkdir -p "${TEST_DIR}" +cp -aT "${SHIPPABLE_BUILD_DIR}" "${TEST_DIR}" +cd "${TEST_DIR}" + +# STAR: HACK install dependencies +retry ansible-galaxy -vvv collection install community.general +retry ansible-galaxy -vvv collection install ansible.netcommon + +retry pip install hcloud +retry pip install netaddr --disable-pip-version-check +retry ansible-galaxy -vvv collection install community.internal_test_tools +# END: HACK + +export PYTHONIOENCODING='utf-8' + +if [ "${JOB_TRIGGERED_BY_NAME:-}" == "nightly-trigger" ]; then + COMPLETE=yes +fi + + +if [ -n "${COMPLETE:-}" ]; then + # disable change detection triggered by setting the COMPLETE environment variable to a non-empty value + export CHANGED="" +elif [[ "${COMMIT_MESSAGE}" =~ ci_complete ]]; then + # disable change detection triggered by having 'ci_complete' in the latest commit message + export CHANGED="" +else + # enable change detection (default behavior) + export CHANGED="--changed" +fi + +if [ "${IS_PULL_REQUEST:-}" == "true" ]; then + # run unstable tests which are targeted by focused changes on PRs + export UNSTABLE="--allow-unstable-changed" +else + # do not run unstable tests outside PRs + export UNSTABLE="" +fi + +# remove empty core/extras module directories from PRs created prior to the repo-merge +find plugins -type d -empty -print -delete + +function cleanup +{ + if [ -d tests/output/junit/ ]; then + cp -aT tests/output/junit/ "$SHIPPABLE_RESULT_DIR/testresults/" + fi + + if [ -d tests/output/data/ ]; then + cp -a tests/output/data/ "$SHIPPABLE_RESULT_DIR/testresults/" + fi + + if [ -d tests/output/bot/ ]; then + cp -aT tests/output/bot/ "$SHIPPABLE_RESULT_DIR/testresults/" + fi +} + +trap cleanup EXIT + +ansible-test env --dump --show --timeout "50" --color -v + +"tests/utils/shippable/check_matrix.py" +"tests/utils/shippable/${script}.sh" "${test}" diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.py b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.py new file mode 100755 index 00000000..fb538271 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3.7 +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import sys +import time + +start = time.time() + +sys.stdin.reconfigure(errors='surrogateescape') +sys.stdout.reconfigure(errors='surrogateescape') + +for line in sys.stdin: + seconds = time.time() - start + sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line)) + sys.stdout.flush() diff --git a/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.sh b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.sh new file mode 100755 index 00000000..77e25783 --- /dev/null +++ b/collections-debian-merged/ansible_collections/hetzner/hcloud/tests/utils/shippable/timing.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -o pipefail -eu + +"$@" 2>&1 | "$(dirname "$0")/timing.py" |