Skip to content

Commit

Permalink
Allow to set user value for the container image (#521)
Browse files Browse the repository at this point in the history
* Allow to set user value for the container image

* Added options.user setting
* Updated documentation with an example
* Added unit tests

Fixes: #506

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>

* Updated indentation

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>

* review comments

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>

* Fix integration tests

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>

---------

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
  • Loading branch information
Akasurde authored May 4, 2023
1 parent b7e922d commit 77f54f0
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 0 deletions.
3 changes: 3 additions & 0 deletions demo/execution-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ images:
# name: registry.fedoraproject.org/fedora:38 # vanilla image!
# name: registry.access.redhat.com/ubi9/ubi:latest # vanilla image!

options:
user: '1000' # (optional) sets the username or UID

dependencies:
python_interpreter:
package_system: python39 # (optional) name of a Python interpreter OS package to install
Expand Down
5 changes: 5 additions & 0 deletions docs/definition.rst
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ builder runtime functionality. Valid keys for this section are:
created (if it doesn't already exist), set to ``root`` group ownership, and ``rwx`` group
permissions recursively applied to it. The default value is ``/runner``.

``user``
This sets the username or UID to use as the default user for the final container image.
The default value ``1000``.


Example ``options`` section:

Expand All @@ -344,6 +348,7 @@ Example ``options`` section:
relax_password_permissions: false
skip_ansible_check: true
workdir: /myworkdir
user: bob
version
*******
Expand Down
5 changes: 5 additions & 0 deletions src/ansible_builder/containerfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ def prepare(self):

self._insert_custom_steps('append_final')
self._prepare_label_steps()
if self.definition.version >= 3 and (uid := self.definition.options['user']):
self._prepare_user_steps(uid)
self._prepare_entrypoint_steps()

def write(self):
Expand Down Expand Up @@ -424,3 +426,6 @@ def _prepare_entrypoint_steps(self):
self.steps.append(f"ENTRYPOINT {ep}")
if cmd := self.definition.container_init.get('cmd'):
self.steps.append(f"CMD {cmd}")

def _prepare_user_steps(self, uid):
self.steps.append(f"USER {uid}")
5 changes: 5 additions & 0 deletions src/ansible_builder/ee_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@
"description": "Path to the system package manager to use",
"type": "string",
},
"user": {
"description": "Sets the username or UID",
"type": "string",
},
"container_init": {
"description": "Customize container startup behavior",
"type": "object",
Expand Down Expand Up @@ -433,3 +437,4 @@ def _handle_options_defaults(ee_def: dict):
'entrypoint': '["/output/scripts/entrypoint", "dumb-init"]',
'cmd': '["bash"]',
})
options.setdefault('user', '1000')
3 changes: 3 additions & 0 deletions test/data/v3/complete/ee.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ build_arg_defaults:
ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: '--foo'
ANSIBLE_GALAXY_CLI_ROLE_OPTS: '--bar'

options:
user: '1001'

dependencies:
ansible_core:
package_pip: ansible-core==2.13
Expand Down
21 changes: 21 additions & 0 deletions test/integration/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ def test_v3_complete(cli, data_dir, tmp_path):
assert 'RUN chmod ug+rw /etc/passwd' in text
assert 'RUN mkdir -p /runner' in text
assert 'ENTRYPOINT ["/output/scripts/entrypoint", "dumb-init"]' in text
assert 'USER 1001' in text

# check additional_build_files
myconfigs_path = tmp_path / constants.user_content_subfolder / "myconfigs"
Expand Down Expand Up @@ -468,3 +469,23 @@ def test_v3_no_workdir(cli, build_dir_and_ee_yml):

assert "WORKDIR" not in text.replace('WORKDIR /build', '') # intermediate stages set WORKDIR- ignore those
assert "mkdir -p /runner" not in text


def test_v3_set_user_id(cli, build_dir_and_ee_yml):
"""
Test that a custom 'options.user' sets it
"""
tmpdir, eeyml = build_dir_and_ee_yml(
"""
version: 3
options:
user: bob
"""
)
cli(f'ansible-builder create -c {tmpdir} -f {eeyml} --output-filename Containerfile')

containerfile = tmpdir / "Containerfile"
assert containerfile.exists()
text = containerfile.read_text()

assert "USER bob" in text
26 changes: 26 additions & 0 deletions test/unit/test_user_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,32 @@ def test_v3_skip_ansible_check_default(self, exec_env_definition_file):
value = definition.raw.get('options', {}).get('skip_ansible_check')
assert value is False

def test_v3_user_id(self, exec_env_definition_file):
"""
Test that options.user defaults to 1000
"""
path = exec_env_definition_file(
"{'version': 3}"
)
definition = UserDefinition(path)
definition.validate()

value = definition.raw.get('options', {}).get('user')
assert value == '1000'

def test_v3_set_user_name(self, exec_env_definition_file):
"""
Test that options.user sets to username
"""
path = exec_env_definition_file(
"{'version': 3, 'options': {'user': 'bob'}}"
)
definition = UserDefinition(path)
definition.validate()

value = definition.raw.get('options', {}).get('user')
assert value == 'bob'


class TestImageDescription:

Expand Down

0 comments on commit 77f54f0

Please sign in to comment.