Skip to content

Commit

Permalink
feat: dokku_image library - support for git:from-image (#126)
Browse files Browse the repository at this point in the history
Add support for creating apps from docker images via `dokku git:from-image`.
  • Loading branch information
fr3fou authored Nov 11, 2021
1 parent cddf335 commit fe5b4a7
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 22 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,40 @@ Manages global ssl configuration.
state: absent
```

### dokku_image

Pull Docker image and deploy app

#### Parameters

|Parameter|Choices/Defaults|Comments|
|---------|----------------|--------|
|app<br /><sup>*required*</sup>||The name of the app|
|build_dir||Specify custom build directory for a custom build context|
|image<br /><sup>*required*</sup>||Docker image|
|user_email||Git user.email for customizing the author's email|
|user_name||Git user.name for customizing the author's name|

#### Example

```yaml
- name: Pull and deploy meilisearch
dokku_image:
app: meilisearch
image: getmeili/meilisearch:v0.24.0rc1
- name: Pull and deploy image with custom author
dokku_image:
app: hello-world
user_name: Elliot Alderson
user_email: [email protected]
image: hello-world:latest
- name: Pull and deploy image with custom build dir
dokku_image:
app: hello-world
build_dir: /path/to/build
image: hello-world:latest
```

### dokku_letsencrypt

Enable or disable the letsencrypt plugin for a dokku app
Expand Down
27 changes: 5 additions & 22 deletions library/dokku_clone.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.dokku_app import (
dokku_app_ensure_present,
)
import subprocess

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.dokku_app import dokku_app_ensure_present
from ansible.module_utils.dokku_git import dokku_git_sha

DOCUMENTATION = """
---
Expand Down Expand Up @@ -59,22 +58,6 @@
"""


def dokku_git_sha(data):
"""Get SHA of current app repository.
Returns `None` if app does not exist.
"""
command_git_report = "dokku git:report {app} --git-sha".format(app=data["app"])
try:
sha = subprocess.check_output(
command_git_report, stderr=subprocess.STDOUT, shell=True
)
except subprocess.CalledProcessError:
sha = None

return sha


def dokku_clone(data):

# create app (if not exists)
Expand All @@ -83,7 +66,7 @@ def dokku_clone(data):
if is_error:
return (is_error, has_changed, meta)

sha_old = dokku_git_sha(data)
sha_old = dokku_git_sha(data["app"])

# sync with remote repository
command_git_sync = "dokku git:sync {app} {repository}".format(
Expand All @@ -107,7 +90,7 @@ def dokku_clone(data):
finally:
meta["present"] = True # meaning: requested *version* of app is present

if data["build"] or dokku_git_sha(data) != sha_old:
if data["build"] or dokku_git_sha(data["app"]) != sha_old:
has_changed = True

return (is_error, has_changed, meta)
Expand Down
127 changes: 127 additions & 0 deletions library/dokku_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import subprocess

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.dokku_app import dokku_app_ensure_present
from ansible.module_utils.dokku_git import dokku_git_sha

DOCUMENTATION = """
---
module: dokku_image
short_description: Pull Docker image and deploy app
options:
app:
description:
- The name of the app
required: True
default: null
aliases: []
image:
description:
- Docker image
required: True
default: null
aliases: []
user_name:
description:
- Git user.name for customizing the author's name
required: False
default: null
aliases: []
user_email:
description:
- Git user.email for customizing the author's email
required: False
default: null
aliases: []
build_dir:
description:
- Specify custom build directory for a custom build context
required: False
default: null
aliases: []
author: Simo Aleksandrov
"""

EXAMPLES = """
- name: Pull and deploy meilisearch
dokku_image:
app: meilisearch
image: getmeili/meilisearch:v0.24.0rc1
- name: Pull and deploy image with custom author
dokku_image:
app: hello-world
user_name: Elliot Alderson
user_email: [email protected]
image: hello-world:latest
- name: Pull and deploy image with custom build dir
dokku_image:
app: hello-world
build_dir: /path/to/build
image: hello-world:latest
"""


def dokku_image(data):
# create app (if not exists)
is_error, has_changed, meta = dokku_app_ensure_present(data)
meta["present"] = False # meaning: requested *version* of app is present
if is_error:
return (is_error, has_changed, meta)

sha_old = dokku_git_sha(data["app"])

# get image
command_git_from_image = "dokku git:from-image {app} {image}".format(
app=data["app"], image=data["image"]
)
if data["user_name"]:
command_git_from_image += " {user_name}".format(user_name=data["user_name"])
if data["user_email"]:
command_git_from_image += " {user_email}".format(user_email=data["user_email"])
if data["build_dir"]:
command_git_from_image += ' --build-dir "{build_dir}"'.format(
build_dir=data["build_dir"]
)
try:
subprocess.check_output(
command_git_from_image, stderr=subprocess.STDOUT, shell=True
)
except subprocess.CalledProcessError as e:
is_error = True
if "is not a dokku command" in str(e.output):
meta[
"error"
] = "Please upgrade to dokku>=0.24.0 in order to use the 'git:from-image' command."
else:
meta["error"] = str(e.output)
return (is_error, has_changed, meta)
finally:
meta["present"] = True # meaning: requested *version* of app is present

if dokku_git_sha(data["app"]) != sha_old:
has_changed = True

return (is_error, has_changed, meta)


def main():
fields = {
"app": {"required": True, "type": "str"},
"image": {"required": True, "type": "str"},
"user_name": {"required": False, "type": "str"},
"user_email": {"required": False, "type": "str"},
"build_dir": {"required": False, "type": "str"},
}

module = AnsibleModule(argument_spec=fields, supports_check_mode=False)
is_error, has_changed, result = dokku_image(module.params)

if is_error:
module.fail_json(msg=result["error"], meta=result)
module.exit_json(changed=has_changed, meta=result)


if __name__ == "__main__":
main()
20 changes: 20 additions & 0 deletions module_utils/dokku_git.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""Utility functions for dokku git related plugins"""
import subprocess


def dokku_git_sha(app):
"""Get SHA of current app repository.
Returns `None` if app does not exist.
"""
command_git_report = "dokku git:report {app} --git-sha".format(app=app)
try:
sha = subprocess.check_output(
command_git_report, stderr=subprocess.STDOUT, shell=True
)
except subprocess.CalledProcessError:
sha = None

return sha
26 changes: 26 additions & 0 deletions molecule/default/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,29 @@
msg: |-
'web: 2' not found in output of 'dokku ps:scale example-app':
{{ example_app_scale_values.stdout }}
# Testing dokku_image
- name: Create a dummy directory for testing
file:
path: /home/dokku/test
state: directory

- name: Deploy meilisearch using dokku_image
dokku_image:
app: ms
user_name: Elliot Alderson
user_email: [email protected]
build_dir: /home/dokku/test
image: getmeili/meilisearch:latest

- name: Get list of apps # noqa 301
command: dokku apps:list
register: dokku_apps

- name: Check that ms is in list of apps
assert:
that:
- "'ms' in dokku_apps.stdout"
msg: |
'ms' not found in output of 'dokku apps:list':
{{ dokku_apps.stdout }}

0 comments on commit fe5b4a7

Please sign in to comment.