Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lock built-in commands to specific digests #38

Draft
wants to merge 48 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f8aa24e
Verify --shell command for many commands, run in parallel
boukeversteegh Apr 11, 2022
c429c38
Remove duplicate test-case
boukeversteegh Apr 11, 2022
9642dff
Force alpine images for go, python, and lock digest
boukeversteegh Apr 11, 2022
026df8f
Run all cases
boukeversteegh Apr 11, 2022
c0e5cfe
Use alpine3.14 for python and rust
boukeversteegh Apr 11, 2022
5004a31
Disable fail fast
boukeversteegh Apr 11, 2022
3e27e9d
Fix double python version listing
boukeversteegh Apr 11, 2022
f180383
Remove digest from python
boukeversteegh Apr 11, 2022
9a35765
Lock dotnet
boukeversteegh Apr 11, 2022
dc04c04
Lock dotnet
boukeversteegh Apr 11, 2022
4ce2e25
Lock go to older version
boukeversteegh Apr 19, 2022
be87829
feat: add --digest and --pull options
boukeversteegh Apr 19, 2022
4f40dba
Lock ruby
boukeversteegh Apr 19, 2022
2016f14
Pull image before running shell test
boukeversteegh Apr 19, 2022
17e093d
feat: add option --entrypoint
boukeversteegh Apr 19, 2022
adca8cb
verbose logging while running --shell test
boukeversteegh Apr 19, 2022
f002d73
Split up test in multiple steps to verify which command breaks
boukeversteegh Apr 19, 2022
c6115f4
Try entrypoint approach
boukeversteegh Apr 19, 2022
df08fe4
Fix test step name
boukeversteegh Apr 19, 2022
8d313d1
Sanity check
boukeversteegh Apr 19, 2022
0cddeaa
Test printing env instead of echoing hostname
boukeversteegh Apr 19, 2022
ff52840
Test manual shell detection
boukeversteegh Apr 19, 2022
e873866
Disable welcome message in --shell
boukeversteegh Apr 19, 2022
ee6d65e
Disable PS1 override in --shell option
boukeversteegh Apr 19, 2022
a3b1bd1
See if quotes make the difference
boukeversteegh Apr 19, 2022
30a8304
Run once (to ensure volumes and network are created)
boukeversteegh Apr 19, 2022
4003753
Do not use full path for entrypoint
boukeversteegh Apr 19, 2022
e9962e0
Determine if test order matters
boukeversteegh Apr 19, 2022
30baa67
Explicit shells per command
boukeversteegh Apr 20, 2022
ed70a03
Remove redundant tests
boukeversteegh Apr 20, 2022
d0b8b48
feat: add --commands to list all available commands
boukeversteegh Apr 20, 2022
6a81b7b
Set configured shell as entrypoint for --shell
boukeversteegh Apr 20, 2022
61b79f9
Compare running with docker-compose
boukeversteegh Apr 20, 2022
896aecb
Pass args in quotes
boukeversteegh Apr 20, 2022
29c2bf3
Use bash for go
boukeversteegh Apr 20, 2022
25d1e8c
Fix test
boukeversteegh Apr 20, 2022
4f1d2f9
Ensure networks are created, similar to docker-compose run
boukeversteegh Apr 20, 2022
bc77d20
Disable compose prerun
boukeversteegh Apr 20, 2022
9b250a1
Disable prerun
boukeversteegh Apr 20, 2022
c94acbc
Add more logging
boukeversteegh Apr 20, 2022
da23fe3
Run test twice
boukeversteegh Apr 20, 2022
2018a8f
Echo hello world
boukeversteegh Apr 20, 2022
67d3d8f
Print error if available
boukeversteegh Apr 20, 2022
3069372
Temporarily disable tty
boukeversteegh Apr 20, 2022
4bf3d0b
Disable double run
boukeversteegh Apr 20, 2022
6d6a36c
Print 'compiled dockerized'
boukeversteegh Apr 20, 2022
9b6d3c8
Only open tty when in terminal
boukeversteegh Apr 20, 2022
b6ec19d
Do not pull image separately
boukeversteegh Apr 20, 2022
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
10 changes: 5 additions & 5 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ DEFAULT_BASE_IMAGE_VERSION=${ALPINE_VERSION}
DEFAULT_BASE=${DEFAULT_BASE_IMAGE}:${DEFAULT_BASE_IMAGE_VERSION}
DOCTL_VERSION=1.70.0
DOLT_VERSION=0.37.9
DOTNET_VERSION=6.0
DOTNET_VERSION=6.0@sha256:a2a8f968b043349b8faa0625c5405ac33da70b3274ff9e17109430f16aa9a3ee
GIT_VERSION=2.32.0
GH_VERSION=2.5.2
GO_VERSION=1.17.8
GO_VERSION=1.17.8-alpine@sha256:c7c94588b6445f5254fbc34df941afa10de04706deb330e62831740c9f0f2030
HASKELL_VERSION=9.2.2
GHCI_VERSION=${HASKELL_VERSION}
HELM_VERSION=3.8.1
Expand All @@ -35,10 +35,10 @@ PROTOC_ARCH=${DEFAULT_ARCH}
PROTOC_BASE=${DEFAULT_BASE}
POSTGRES_VERSION=14.2
PSQL_VERSION=${POSTGRES_VERSION}
PYTHON_VERSION=3.10
PYTHON_VERSION=3.10-alpine
PYTHON2_VERSION=2.7.18
RUBY_VERSION=3.1.1
RUST_VERSION=1.59.0
RUBY_VERSION=3.1.1-alpine3.14@sha256:e5a66799d2e82e1434ae4565842bcfd03bc0c2fb4394811ebedcae967fc77919
RUST_VERSION=1.59.0-alpine3.14@sha256:86d063b20c2214fe5292683e9386f178462405880fb9507c0e765482eb126789
RUSTC_VERSION=${RUST_VERSION}
S3CMD_BASE=python:${PYTHON_VERSION}-${DEFAULT_BASE_IMAGE}
S3CMD_VERSION=2.2.0
Expand Down
18 changes: 12 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ on:
jobs:
ShellTest:
strategy:
fail-fast: true
fail-fast: false
matrix:
command:
- go
- aws
- dotnet
- go
- java
- node
- perl
- php
- python
- ruby
- rustc
- zip
runs-on: ubuntu-latest
Expand All @@ -23,11 +29,11 @@ jobs:
uses: actions/checkout@v2
- name: Compile
run: bin/dockerized --compile
- name: "Test: dockerized --shell ${{matrix.command}}"
env:
COMMAND: "${{matrix.command}}"
- name: "dockerized --shell ${{matrix.command}}"
run: bin/dockerized -v --shell ${{matrix.command}} -c env | tee ~/shell.log
- name: "Assert"
run: |
bin/dockerized --shell $COMMAND -c 'echo $HOST_HOSTNAME' | tee ~/shell.log
echo "Test --shell"
grep $(hostname) ~/shell.log
IntegrationTest:
runs-on: ubuntu-latest
Expand Down
5 changes: 3 additions & 2 deletions bin/dockerized
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,13 @@ if [ "$DOCKERIZED_COMPILE" ] || [ ! -f "$DOCKERIZED_BINARY" ]; then
fi

if [ $? -ne 0 ]; then
echo "Failed to compile dockerized" >&2
echo "Failed to compile dockerized." >&2
exit 1
fi

echo "Compiled dockerized." >&2

if [ $# -eq 0 ]; then
echo "Compiled dockerized" >&2
exit 0
fi
fi
Expand Down
6 changes: 5 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ services:
- "${HOME:-home}/.dockerized/apps/dolt:/root"
entrypoint: [ "dolt" ]
dotnet:
image: "mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-alpine"
image: "mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}"
entrypoint: [ "dotnet" ]
gh:
image: "gh:${GH_VERSION}"
Expand Down Expand Up @@ -108,6 +108,8 @@ services:
environment:
GOOS: "${GOOS:-}"
GOARCH: "${GOARCH:-}"
labels:
net.dockerized.shell: "/bin/bash"
gofmt:
<<: *go
entrypoint: [ "gofmt" ]
Expand Down Expand Up @@ -153,6 +155,8 @@ services:
perl:
image: perl:${PERL_VERSION}
entrypoint: [ "perl" ]
labels:
net.dockerized.shell: "${PERL_SHELL:-/bin/bash}"
php:
image: "php:${PHP_VERSION}"
psql:
Expand Down
106 changes: 68 additions & 38 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import (
"github.com/compose-spec/compose-go/types"
dockerized "github.com/datastack-net/dockerized/pkg"
"github.com/datastack-net/dockerized/pkg/help"
"github.com/datastack-net/dockerized/pkg/labels"
util "github.com/datastack-net/dockerized/pkg/util"
"github.com/docker/compose/v2/pkg/api"
"github.com/fatih/color"
"github.com/moby/term"
"os"
"path/filepath"
"strings"
Expand All @@ -33,8 +34,12 @@ func RunCli(args []string) (err error, exitCode int) {
var optionVerbose = hasKey(dockerizedOptions, "--verbose") || hasKey(dockerizedOptions, "-v")
var optionShell = hasKey(dockerizedOptions, "--shell")
var optionBuild = hasKey(dockerizedOptions, "--build")
var optionPull = hasKey(dockerizedOptions, "--pull")
var optionVersion = hasKey(dockerizedOptions, "--version")
var optionDigest = hasKey(dockerizedOptions, "--digest")
var optionPort = hasKey(dockerizedOptions, "-p")
var optionEntrypoint = hasKey(dockerizedOptions, "--entrypoint")
var optionCommands = hasKey(dockerizedOptions, "--commands")

dockerizedRoot := dockerized.GetDockerizedRoot()
dockerized.NormalizeEnvironment(dockerizedRoot)
Expand All @@ -61,7 +66,7 @@ func RunCli(args []string) (err error, exitCode int) {
}

if commandName == "" || optionHelp {
err := help.Help(composeFilePaths)
err := help.Help()
if err != nil {
return err, 1
}
Expand All @@ -74,7 +79,7 @@ func RunCli(args []string) (err error, exitCode int) {

if commandVersion != "" {
if commandVersion == "?" {
err = dockerized.PrintCommandVersions(composeFilePaths, commandName, optionVerbose)
err = dockerized.PrintCommandVersions(commandName, optionVerbose)
if err != nil {
return err, 1
} else {
Expand All @@ -85,7 +90,7 @@ func RunCli(args []string) (err error, exitCode int) {
}
}

project, err := dockerized.GetProject(composeFilePaths)
project, err := dockerized.GetProject()
if err != nil {
return err, 1
}
Expand All @@ -97,14 +102,20 @@ func RunCli(args []string) (err error, exitCode int) {
containerCwd += "/" + hostCwdDirName
}

if optionCommands {
for _, service := range project.Services {
fmt.Printf("%s\n", service.Name)
}
return nil, 0
}
runOptions := api.RunOptions{
Service: commandName,
Environment: []string{
"HOST_HOSTNAME=" + hostName,
},
Command: commandArgs,
AutoRemove: true,
Tty: true,
Tty: term.IsTerminal(os.Stdout.Fd()),
WorkingDir: containerCwd,
}

Expand Down Expand Up @@ -142,29 +153,47 @@ func RunCli(args []string) (err error, exitCode int) {
if optionVerbose {
fmt.Printf("Building container image for %s...\n", commandName)
}
err := dockerized.DockerComposeBuild(composeFilePaths, api.BuildOptions{
err := dockerized.DockerComposeBuild(api.BuildOptions{
Services: []string{commandName},
})

if err != nil {
return err, 1
}
} else if optionPull {
err = dockerized.Pull(commandName)
if err != nil {
return err, 1
}
if !optionDigest {
return nil, 0
}
}

if optionDigest {
digest, err := dockerized.GetDigest(commandName)

if err != nil {
return err, 0
}
fmt.Println(digest)
return nil, 0
}

if optionShell && optionEntrypoint {
return fmt.Errorf("--shell and --entrypoint are mutually exclusive"), 1
}

if optionShell {
if optionVerbose {
fmt.Printf("Opening shell in container for %s...\n", commandName)

if len(commandArgs) > 0 {
fmt.Printf("Passing arguments to shell: %s\n", commandArgs)
}
fmt.Printf("Setting up shell in container for %s...\n", commandName)
}

var ps1 = fmt.Sprintf(
"%s %s:\\w \\$ ",
color.BlueString("dockerized %s", commandName),
color.New(color.FgHiBlue).Add(color.Bold).Sprintf("\\u@\\h"),
)
//var ps1 = fmt.Sprintf(
// "%s %s:\\w \\$ ",
// color.BlueString("dockerized %s", commandName),
// color.New(color.FgHiBlue).Add(color.Bold).Sprintf("\\u@\\h"),
//)
var welcomeMessage = "Welcome to dockerized shell. Type 'exit' or press Ctrl+D to exit.\n"
welcomeMessage += "Mounted volumes:\n"

Expand All @@ -179,30 +208,26 @@ func RunCli(args []string) (err error, exitCode int) {
}
welcomeMessage = strings.ReplaceAll(welcomeMessage, "\\", "\\\\")

shells := []string{
"bash",
"zsh",
"sh",
}
var shellDetectionCommands []string
for _, shell := range shells {
shellDetectionCommands = append(shellDetectionCommands, "command -v "+shell)
var shell = "sh"
if service.Labels[labels.Shell] != "" {
shell = service.Labels[labels.Shell]
}
for _, shell := range shells {
shellDetectionCommands = append(shellDetectionCommands, "which "+shell)
}

var cmdPrintWelcome = fmt.Sprintf("echo '%s'", color.YellowString(welcomeMessage))
var cmdLaunchShell = fmt.Sprintf("$(%s)", strings.Join(shellDetectionCommands, " || "))

runOptions.Environment = append(runOptions.Environment, "PS1="+ps1)
runOptions.Entrypoint = []string{"/bin/sh"}
runOptions.Entrypoint = []string{shell}
runOptions.Command = commandArgs
}

if len(commandArgs) > 0 {
runOptions.Command = []string{"-c", fmt.Sprintf("%s; %s \"%s\"", cmdPrintWelcome, cmdLaunchShell, strings.Join(commandArgs, "\" \""))}
} else {
runOptions.Command = []string{"-c", fmt.Sprintf("%s; %s", cmdPrintWelcome, cmdLaunchShell)}
if optionEntrypoint {
var entrypoint = dockerizedOptions["--entrypoint"]
if optionVerbose {
fmt.Printf("Setting entrypoint to %s\n", entrypoint)
}
runOptions.Entrypoint = strings.Split(entrypoint, " ")
}

if optionVerbose {
fmt.Printf("Entrypoint: %s\n", runOptions.Entrypoint)
fmt.Printf("Command: %s\n", runOptions.Command)
}

if !contains(project.ServiceNames(), commandName) {
Expand All @@ -215,23 +240,28 @@ func RunCli(args []string) (err error, exitCode int) {
return dockerized.DockerRun(image, runOptions, volumes)
}

return dockerized.DockerComposeRun(project, runOptions, volumes, serviceOptions...)
return dockerized.DockerComposeRun(project, runOptions, volumes, optionVerbose, serviceOptions...)
}

func parseArguments(args []string) (map[string]string, string, string, []string) {
var options = []string{
"--shell",
"--build",
"-h",
"--help",
"-p",
"--pull",
"--digest",
"--commands",
"--shell",
"--entrypoint",
"-v",
"--verbose",
"--version",
}

var optionsWithParameters = []string{
"-p",
"--entrypoint",
}

commandName := ""
Expand Down
16 changes: 16 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Context struct {
}

func TestHelp(t *testing.T) {
defer context().Restore()
output := testDockerized(t, []string{"--help"})
assert.Contains(t, output, "Usage:")
}
Expand Down Expand Up @@ -245,6 +246,21 @@ func TestOverrideVersionWithGlobalEnvFile(t *testing.T) {
assert.Contains(t, output, "3.8.0")
}

func TestEnvironmentHostName(t *testing.T) {
defer context().Restore()
expectedHostName, err := os.Hostname()
assert.Nil(t, err)
assert.NotNil(t, expectedHostName)
var output = testDockerized(t, []string{"--shell", "go", "-c", "echo $HOST_HOSTNAME"})
assert.Contains(t, output, expectedHostName)
}

func TestShell(t *testing.T) {
defer context().Restore()
var output = testDockerized(t, []string{"--shell", "go", "--version"})
assert.Contains(t, output, "GNU bash")
}

func capture(callback func()) string {
read, write, _ := os.Pipe()
os.Stdout = write
Expand Down
Loading