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

Go Docker API #21

Merged
merged 4 commits into from
Aug 29, 2018
Merged

Go Docker API #21

merged 4 commits into from
Aug 29, 2018

Conversation

asmr-hex
Copy link
Collaborator

@asmr-hex asmr-hex commented Aug 22, 2018

Overview

instead of using os/exec.Command to start docker containers, we use the official Docker Go API. This arguably makes the code more readable/maintainable and is possibly more platform independent (we don't have to rely on the assumption that we are running in a UNIX-like shell like we do when we make call outs to a shell using os/exec/Command).

this PR resolves issue #6

Major Changes

  • introduce DockerClient and result/error channels as fields in sandbox struct
  • set docker env var in sandbox constructor
  • add (commented out) docker network setup in sandbox constructor (TODO breadcrumb)
  • introduce PrepareContainer submethod of (*sandbox).prepare()
  • create docker container and redirect stdout/err to main process in PrepareContainer
  • start container using Docker API in (*sandbox).execute()
  • wait for sandbox to finish running and be removed with select statement
  • remove spawnDocker method (replaced by Docker API methods).
  • introduce more comprehensive/consolidated error handling in sandbox methods
  • update comments in script.sh
  • vendor dependencies using govendor

Notes

it is probably a good idea to start vendoring our dependencies. i chose the govendor tool just because i am most familiar with it, though it would be very easy to swap this out for another tool if anyone has a strong preference. On that note, there are a bunch of vendored files in this PR (sorry), but Github is smart enough to collapse them so you don't have to look at them.

connorwalsh added 4 commits August 21, 2018 22:37
Notes:
* create godoc during this refactor and remove `docs.md`
Major Changes:
* connect to docker client in #newSandbox constructor
* break up #prepare into #PrepareTmpDir and #PrepareContainer
* implement #PrepareContainer for setting up sandbox docker container
* refactor #execute to start docker container and wait for completion
* return errors from all sandbox methods rather than logging
  errors (this way, calling function can decide how to proceed on error)
* assign sandbox ID corresponding to container id
* create tmpDirPrefix constant
* add docstrign comments

Todos:
* must include test coverage.
…nRemoved

Notes:
for some reason, WaitConditionStoped is insufficient and we must use
WaitconditionRemoved. The prior resulted in a race condition in which
the stdout/err was not finished writing to the
files (errors/completed) specified in the `script.sh` bash script used
to compile/run the user code.
@asmr-hex asmr-hex added the enhancement New feature or request label Aug 22, 2018
@asmr-hex asmr-hex requested review from frenata and nefelin August 22, 2018 15:54
@frenata
Copy link
Owner

frenata commented Aug 23, 2018

Nice stuff. I'll check this out in detail later this week/weekend.

re: vendoring, the upcoming release includes an experimental new dependency resolution tool that should eliminate the need to do so (instead we'd have roughly a packages.json equivalent), it'll be cool to experiment with it when it hits.

@asmr-hex
Copy link
Collaborator Author

@frenata, awesome! thanks!

ah interesting, i wasn't aware of go 1.11-- looks like there are some good changes here. i think experimenting with the new dependency management tool would be a great idea.

Copy link
Owner

@frenata frenata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid improvement.

tmpFolder, err := ioutil.TempDir(s.options.folder, "xaqt-")
// prepares the execution environment and the sandbox docker container.
//
func (s *sandbox) prepare() error {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some important cleanup such that we deal with errors more robustly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

//log.Println(s.code)
// write source file into tmp dir
// TODO (cw|4.29.2018) we should be able to write an arbitrary number of files
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense! iow, consume a list of source files and map WriteFile over it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, i meant to take this comment out-- it was meant to say "write an arbitrary number of resource files" (i.e. files which the user submitted source can read and write to if it needs to load, say parameters or some data for the code to work). this has been addressed in the PR so i can take out this TODO.

dockerCommand := s.options.path + "/DockerTimeout.sh"
// setup stdout stream from container
// TODO (cw|8.21.2018) do we need this?
hijackedResp, err := s.docker.ContainerAttach(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

optionalExecutable := s.language.OptionalExecutable
flags := s.language.CompilerFlags
// create docker container for executing user code
_, err = s.docker.ContainerCreate(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to close/destroy/cleanup this container in some fashion within a defer block?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when the container is configured it has been set to be auto removed once the process in the container completes (see this part of the container config)

return string(outputBytes), err
return string(outputBytes), nil
case err = <-s.errChan:
// the damn container errored
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😆

*TODO (cw|4.28.2018) create godocs instead of this file...these are mostly notes for myself during development.*

# Public Types
* **`xaqt.Context`**: entrypoint into all functionality. TODO Propose renaming?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah despite naming it that, I don't love it... especially now that we're using the Context library.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, i feel you, naming is hard and often doesn't feel like it holds up over time as the code progresses-- luckily this is a painless refactor at this point, so if we decide on a good rename we can change it. i won't do it in this PR since its not super relevant...but we can think it over :)

@asmr-hex asmr-hex merged commit 3498631 into master Aug 29, 2018
@asmr-hex asmr-hex deleted the go-docker-api branch August 29, 2018 22:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants