Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
"name": "Sandock DevContainer",
"image": "mcr.microsoft.com/devcontainers/python:1-3.9-bullseye",
"features": {
"ghcr.io/devcontainers-extra/features/poetry:2": {}
"ghcr.io/devcontainers-extra/features/poetry:2": {
"version": "2.1.4"
},
"ghcr.io/devcontainers-extra/features/go-task:1": {
"version": "3.44.1"
}
},
"customizations": {
"vscode": {
Expand All @@ -11,5 +16,5 @@
]
}
},
"postCreateCommand": "poetry install --with=dev && cp examples/complex.yml ~/.sandock.yml"
"postCreateCommand": "task install-dev && cp examples/complex.yml ~/.sandock.yml"
}
10 changes: 8 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ jobs:
with:
persist-credentials: false

- name: Install Task
uses: arduino/setup-task@v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
Expand All @@ -47,11 +53,11 @@ jobs:
key: venv-sndk-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}

- name: Install dependencies
run: make install-dev
run: task install-dev
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'

- name: Run tests and generate coverage report
run: make test-all
run: task test-all

- name: Upload coverage reports to Codecov
if: github.ref == 'refs/heads/main'
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change Log

## [0.5.0]

### Features and Enhancements

- [cli] add overrides for container ports publishing
- [dev] migrate gnu-make to go-task

## [0.4.0]

### Features and Enhancements
Expand Down
24 changes: 0 additions & 24 deletions Makefile

This file was deleted.

12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ sample backup-restore workflows:

### Requirements

- [GNU Make](https://www.gnu.org/software/make/)
- [Task](https://taskfile.dev)
- [Poetry](https://python-poetry.org/docs/#installation)

### Dev Dependencies
Expand All @@ -423,10 +423,12 @@ poetry install --with=dev

### Shortcuts

- `make test`, run unit test.
- `make tidy`, make code tidier using [black](https://github.com/psf/black). you might execute this before running style check linter.
- `make lint`, run style and type check.
- `make test-all`, combine unit test and style+type check.
- `task test`, run unit test.
- `task tidy`, make code tidier using [black](https://github.com/psf/black). you might execute this before running style check linter.
- `task lint`, run style and type check.
- `task test-all`, combine unit test and style+type check.

to list the others `task --list-all`

## 💪🏻 Contributing

Expand Down
46 changes: 46 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
version: '3'

tasks:
poetry:
internal: true
requires:
vars: [ARGS]
vars:
SUB_CMD: '{{.SUB_CMD | default "run"}}'
cmds:
- 'poetry {{.SUB_CMD}} {{.ARGS}}'

install-dev:
cmds:
- task: poetry
vars:
SUB_CMD: install
ARGS: --with=dev

test:
cmds:
- for:
- run --source=sandock -m unittest discover -s tests
- report
- html
- xml
task: poetry
vars: {ARGS: 'coverage {{.ITEM}}'}

tidy:
cmds:
- task: poetry
vars: {ARGS: black sandock tests}

lint:
cmds:
- for:
- mypy .
- flake8 sandock
task: poetry
vars: {ARGS: '{{.ITEM}}'}

test-all:
cmds:
- task: test
- task: lint
78 changes: 78 additions & 0 deletions examples/portable_devops_tools.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
backup:
volume_labels: &backup-vol
sandock_backup: "true"

volumes:
ssh_config:
labels:
<<: *backup-vol
gcloud_config:
labels:
<<: *backup-vol

programs:
devopsh:
image: portable-devopsh
env:
HISTFILE: /root/.lokal/bash_history
extra_run_args:
- "--privileged"
build:
dockerfile_inline: |
FROM ubuntu:22.04

COPY --from=docker:28.1-cli /usr/local/bin/docker /usr/local/bin/

ENV PATH=$PATH:/root/.local/bin:/root/.local/share/mise/shims
RUN apt update && apt install -y vim ca-certificates curl unzip openssh-client
RUN curl https://mise.run | sh
RUN echo 'eval "$(/root/.local/bin/mise activate bash)"' >> /root/.bashrc && mkdir -p /root/.config/mise
RUN cat <<EOF > /root/.config/mise/config.toml
[tools]
python = "3.11"
go = "1.23"
jq = "latest"
packer = "1.9.4"
task = "latest"
terraform = "1.11.4"
terraform-docs = "latest"
tflint = "latest"
ansible = "11.3.0"
uv = "latest"
pipx = "latest"
vendir = "latest"
EOF
# gcloud required python installed first
RUN <<EOF
mise activate bash
mise install
mise use --global [email protected]
EOF

# install molecule devs
RUN cat <<EOF > /tmp/requirements_dev.txt
pytest-testinfra==10.2.2
molecule==25.4.0
molecule-plugins[docker]==23.7.0
ansible-lint==25.5.0
docsible==0.7.22
molecule-plugins[gce]==23.7.0
EOF

RUN pip3 install -r /tmp/requirements_dev.txt

# go tools
RUN go install \
github.com/suzuki-shunsuke/tfcmt/v4/cmd/tfcmt@latest
hostname: infra-hub
exec: /bin/bash
aliases:
gcloud: gcloud
ansible: ansible
tf: terraform
task: task
packer: task
volumes:
- gcloud_config:/root/.config/gcloud
- ssh_config:/root/.ssh
- /var/run/docker.sock:/var/run/docker.sock
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "sandock"
version = "0.4.0"
version = "0.5.0"
description = "CLI tool for sandbox execution using container approach"
authors = [{ name = "Imam Omar Mochtar", email = "[email protected]" }]
license = { text = "MIT" }
Expand Down
9 changes: 9 additions & 0 deletions sandock/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ class CmdRun(BaseCommand):

@property
def overrides_args(self) -> ArgumentParser:
"""
list of injected additional parameters for running docker run args
"""
oparser = ArgumentParser(description="overriding parameters")

oparser.add_argument(
Expand Down Expand Up @@ -339,6 +342,12 @@ def overrides_args(self) -> ArgumentParser:
help="set environment in KEY=VALUE format",
)

oparser.add_argument(
self.override_arg(name="ports"),
action="append",
help="publish container ports",
)

oparser.add_argument(
self.override_arg(name="help"),
action="store_true",
Expand Down
11 changes: 9 additions & 2 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,22 @@ def test_main(self, sandbox_exec_mock: MagicMock) -> None:
remote = MagicMock()
sandbox_exec_mock.return_value = remote

provided_args = ["--sandbox-arg-hostname=change_host", "--version"]
provided_args = [
"--sandbox-arg-hostname=change_host",
"--sandbox-arg-ports=8080:8080",
"--sandbox-arg-ports=8081:8081",
"--version"]
with self.obj(
args=Namespace(program="pydev", program_args=provided_args),
) as o:
o.main()

self.assertDictEqual(
sandbox_exec_mock.call_args[1]["overrides"],
dict(hostname="change_host", allow_home_dir=False),
dict(
hostname="change_host",
allow_home_dir=False,
ports=["8080:8080", "8081:8081"]),
)
remote.do.assert_called_once()
self.assertListEqual(
Expand Down
11 changes: 6 additions & 5 deletions tests/test_sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,22 +349,23 @@ def test_ensure_custom_image_exists(self) -> None:

@mock.patch.dict(os.environ, dict(HOME="/home/user1"))
@mock.patch.object(SandboxExec, "custom_image_dockerfile_store")
def test_ensure_custom_image_escape_homedir(self, dockerfile_store: MagicMock) -> None:
def test_ensure_custom_image_escape_homedir(
self, dockerfile_store: MagicMock
) -> None:
"""
escape home dir alias for dockerFile and context
"""
cfg = dummy_main_cfg(
program_kwargs=dict(
image="pydev:base",
build=dict(
dockerFile="${HOME}/path/to/Dockerfile",
context="${HOME}/path/to"
),
dockerFile="${HOME}/path/to/Dockerfile", context="${HOME}/path/to"
),
)
)
shell_mock_side_effects = [
dict(returncode=1), # docker image inspect for pydev:base
dict(returncode=0), # docker image build for pydev:base
dict(returncode=0), # docker image build for pydev:base
]
with mock_shell_exec(side_effects=shell_mock_side_effects) as rs:
o = self.obj(cfg=cfg)
Expand Down
6 changes: 4 additions & 2 deletions tests/test_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ def test_volume_list(self) -> None:
mock_sh.call_args_list[0].args[0],
"docker volume ls --format=json --filter=label=label1='ok' --filter=label=label2='ok'",
)

@patch.object(VolumeMgr, "volume_list")
def test_created_by_sandock(self, mock_volume_list: MagicMock) -> None:
o = self.obj()
o.created_by_sandock
mock_volume_list.assert_called_once_with(label_filters={"created_by.sandock": "true"})
mock_volume_list.assert_called_once_with(
label_filters={"created_by.sandock": "true"}
)

def test_vol_exists(self) -> None:
o = self.obj()
Expand Down