composify 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 82d33d6cbdc717e2ae86615ec296753c3ec29045
4
+ data.tar.gz: 6fd8fb259a1b42d746f838c37ce8d57c3ff28b1d
5
+ SHA512:
6
+ metadata.gz: 84a65c1fd5be49239ac99da8e100301441ea22bfab200b9a2141b412083028d87edabea12d81869129a3545c291a03beb6e8e08084bc8e6ac7bc65eaa2cbefc9
7
+ data.tar.gz: 13e77cb120ff322910200f77fe229cb61177a1a30a73b00553bd923fa12de68689b9e76a00ba9b93166292b76b24e8381bc09c3cef9738bb76900a96528d6e2b
@@ -0,0 +1,70 @@
1
+ Sanely generate the infrastructure needed for developing a multi-component service in Docker.
2
+
3
+ Generates the following tree:
4
+
5
+ ```
6
+ <app root>
7
+ ├── Dockerfile.base
8
+ ├── Dockerfile.development # You'll install testing libraries and such in here.
9
+ ├── Makefile
10
+ ├── Makefile.internal
11
+ ├── bin
12
+ │   ├── entrypoint.erb.sh
13
+ │   └── make # In the Dockerfile, symlinked to /usr/local/bin/make
14
+ └── docker-compose.yml
15
+ ```
16
+
17
+ # Installation
18
+
19
+ * ruby > 2.1 is required.
20
+ * `gem install mocker`
21
+
22
+ ## Make Targets
23
+
24
+ * `make` - initialize everything, shortcut for
25
+ - `pull`
26
+ - `images`
27
+ - `start_resources`
28
+ - `setup`
29
+ - `build`
30
+ * `make pull` - Pull all image dependencies
31
+ * `make images` - Build all images that need building
32
+ * `make setup` - run any setup or seeding that is needed.
33
+ * `make start` - start application containers
34
+ * `make stop` - stop application containers
35
+ * `make implode` - `docker-compose down --rmi all --volumes`
36
+ * `make shell` - Run a shell container
37
+ * `make production` - Build the non-development image
38
+ * `make build` - An example for how to pass-through to the `Makefile.internal` (TODO)
39
+
40
+ And, many more. See the Makefile
41
+
42
+ ## Development Workflow
43
+
44
+ ### Initial
45
+
46
+ ```shell
47
+ make && make up
48
+ ```
49
+
50
+ ### Code Iterations
51
+
52
+ 1. Make your code changes
53
+ 2. If using a compiled language, `make build` (or any pass-through target)
54
+ 3. `make run`, or `make up` depending on how you wish to see output.
55
+
56
+ ### Production (Non-Development) builds
57
+
58
+ Building the production image is pretty easy. Although, instead of thinking of it as a 'production' image, think of it instead as a `non-development` image. Basically, your production image just doesn't have some of the development and testing tools installed. Otherwise, it's the same. You can see this because the Dockerfile chain is `Dockerfile.base -> Dockerfile.development`. The "production" image just doesn't have the development image as layers on top of the base image.
59
+
60
+ ## Notes & Explainations
61
+
62
+ * The main thing going on here is that your main services in the `docker-compose.yml` file have a bind-mounted source directory.
63
+ * Once you run this project, all the generated files constitue the whole thing. After initializing the project with `mocker init`, you do not need `mocker` any longer. Nor do any team members ever need to install it. You are free to modify and change anything that you want.
64
+
65
+ ## TODO
66
+
67
+ 1. Still need to work on the templates & generation if working on a compiled
68
+ project such as go, c, rust, etc.
69
+ 2. Still need to add templates and such for projects like react that do live
70
+ recompilation and inotify/fswatch types of things.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'composify'
4
+
5
+ Composify::CLI.main( ARGV )
@@ -0,0 +1,43 @@
1
+ lib_path = "./lib"
2
+ spec_path = "./spec"
3
+ bin_path = "./bin"
4
+
5
+ libs = Dir.glob("#{lib_path}/**/*.rb")
6
+ libs += Dir.glob("#{lib_path}/**/*.erb")
7
+
8
+ specs = Dir.glob("#{spec_path}/**/*.rb")
9
+ bins = Dir.glob("#{bin_path}/**/*")
10
+
11
+ flist = libs + specs + bins
12
+ flist << "composify.gemspec"
13
+ flist << "README.md"
14
+
15
+ require_relative './lib/version'
16
+
17
+ summary = <<-EOD
18
+ A config generation library to generate a few Dockerfiles, Makefile, and
19
+ docker-compose.yml file that will get everything setup for local docker
20
+ development. Specifically meant for use with non-trivial development setups.
21
+ EOD
22
+
23
+ Gem::Specification.new do |gem|
24
+ gem.name = "composify"
25
+ gem.version = Composify::VERSION
26
+ gem.authors = ["Brett Nakashima"]
27
+ gem.email = ["brettnak@gmail.com"]
28
+ gem.description = "Docker development project generator"
29
+ gem.summary = summary
30
+
31
+ # TODO: Rename this repo to match the gem name
32
+ gem.homepage = "http://gitlab.com/brettnak/mocker"
33
+
34
+ gem.files = flist
35
+ gem.executables = bins.map{ |f| File.basename(f) }
36
+ gem.test_files = specs
37
+ gem.require_paths = ["lib/"]
38
+
39
+ gem.add_development_dependency 'rspec', '~> 3.1'
40
+ gem.add_development_dependency 'trollop', '~> 2.1'
41
+
42
+ gem.license = "MIT"
43
+ end
@@ -0,0 +1,107 @@
1
+ require 'trollop'
2
+ require 'erb'
3
+ require 'fileutils'
4
+
5
+ require_relative './version'
6
+
7
+ module Composify
8
+ class Template
9
+ # TODO: Make these work on windows?
10
+ FILE_LIST = {
11
+ :entrypoint => './templates/bin/entrypoint.sh.erb',
12
+ :docker_compose => './templates/docker-compose.yml.erb',
13
+ :dockerfile_base => './templates/Dockerfile.erb',
14
+ :dockerfile_development => './templates/Dockerfile.development.erb',
15
+ :makefile => './templates/Makefile.erb',
16
+ # :makefile_internal => './templates/Makefile.internal.erb',
17
+ }
18
+
19
+ def initialize( file )
20
+ @file = file
21
+ end
22
+
23
+ def destination
24
+ return @_destination ||= @file.gsub( /^\.\/templates\//, './' ).gsub(/\.erb/, '')
25
+ end
26
+
27
+ # bind - the binding to use for ERB#result
28
+ def result( bind )
29
+ ERB.new(
30
+ File.read( File.expand_path( File.join("..", @file), __FILE__ ) ),
31
+ nil,
32
+ '-'
33
+ ).result( bind )
34
+ end
35
+
36
+ # bind - the binding to use for ERB#result
37
+ def write( bind, force: false )
38
+ if File.exists?( destination ) && !force
39
+ STDERR.puts( "File already exists at #{destination}. Refusing to overwrite" )
40
+ return
41
+ end
42
+
43
+ if (dirname = File.dirname(destination)) != "."
44
+ FileUtils.mkdir_p( dirname )
45
+ end
46
+
47
+ puts "Attempting to write #{destination}"
48
+ File.open( destination, "w" ) do |f|
49
+ contents = result( bind )
50
+ f.write( contents )
51
+ end
52
+ end
53
+ end
54
+
55
+ class CLI
56
+ def self.main( argv )
57
+ cli = self.new( argv )
58
+ cli.generate
59
+ end
60
+
61
+ def self.from_trollop( argv )
62
+ opts = Trollop::options(argv) do
63
+ version "mocker #{Composify::VERSION}"
64
+ banner "Generate a docker-development environment.\nNOTE: The name of your project is the directory"
65
+ opt :base, "Base image of your application", :type => :string, :required => true
66
+ opt :compilable, "Does your application code needs to be compiled?", :type => :bool, :default => false, :short => "C"
67
+ opt :components, "The names of your application services, ie: api, scheduler, etc.", :type => :strings, :required => true
68
+ opt :resource, "[ resource_name, resource_image ] The resources you will use. May be specified more than once.", :type => :strings, :multi => true
69
+ opt :force, "Overwrite any files that exist", :type => :bool, :default => false
70
+ end
71
+
72
+ opts[:resources] = opts[:resource].map{ |e| parse_resource(e) }
73
+
74
+ opts[:root] = Dir.pwd
75
+ opts[:project_name] = File.basename( Dir.pwd ).gsub(/[^a-zA-Z0-9_]/, '')
76
+
77
+ return opts
78
+ end
79
+
80
+ # definition is an array like this:
81
+ # [ resource_name, image ]
82
+ # Returns: [{ :name => "<resource_name>", :image => "<image_url>" }, ... ]
83
+ def self.parse_resource( definition )
84
+ return {
85
+ :name => definition[0],
86
+ :image => definition[1]
87
+ }
88
+ end
89
+
90
+ def initialize( argv )
91
+ @argv = ARGV
92
+ end
93
+
94
+ def options
95
+ return @_options ||= self.class.from_trollop( @argv )
96
+ end
97
+
98
+ def generate
99
+ b = binding
100
+ Template::FILE_LIST.each_pair do |_, file|
101
+ template = Template.new( file )
102
+ template.write( b, force: options[:force] )
103
+ end
104
+ end
105
+ end
106
+
107
+ end
@@ -0,0 +1,8 @@
1
+ FROM <%= options[:project_name] %>_base:latest
2
+
3
+ # This is where you'd install stuff like test libraries
4
+ # Or, for a ruby project, where you'd install the bundle with everything
5
+ # rather than just the production stuff
6
+
7
+ # Do not put ENTRYPOINT or CMD in here. Instead, let them be inherited from the
8
+ # Dockerfile.base
@@ -0,0 +1,18 @@
1
+ FROM <%= options[:base] %>
2
+
3
+ # Depending on the docker image you're using, you may need to specify a
4
+ # different workdir, or even not set one and use the perscribed one from the
5
+ # base image. If you do change it, don't forget to change where the
6
+ # bind-mounting happens in the compose file.
7
+ <%- workdir = "/src" %>
8
+
9
+ RUN mkdir -p <%= workdir %>
10
+
11
+ WORKDIR <%= workdir %>
12
+
13
+ ADD . <%= workdir %>
14
+
15
+ # Do any other initializations steps here.
16
+
17
+ ENTRYPOINT [ <%= workdir %>/bin/entrypoint.sh ]
18
+ CMD [ "pass" ]
@@ -0,0 +1,71 @@
1
+ DOCKER ?= docker
2
+ DOCKER_COMPOSE ?= docker-compose
3
+ APPLICATION_SERVICES = <%= options[:components].join(" ") %>
4
+ RESOURCE_SERVICES = <%= options[:resources].map{ |e| e[:name] }.join(" ") %>
5
+ COMPOSE_SHELL = ${DOCKER_COMPOSE} run --rm shell
6
+
7
+ default_target: initialize
8
+
9
+ initialize:
10
+ $(MAKE) images
11
+ $(MAKE) start
12
+ $(MAKE) setup
13
+ @echo "Everything initialized and started."
14
+
15
+ images: pull
16
+ @echo "Building base && base_development"
17
+ @${DOCKER_COMPOSE} build base
18
+ @${DOCKER_COMPOSE} build base_development
19
+ @echo "Images are prepped. Run 'make start' to set things up"
20
+
21
+ pull:
22
+ @echo "Pulling all images"
23
+ # pull --ignore-pull-failures has been broken since compose 1.13
24
+ # https://github.com/docker/compose/issues/4377
25
+ # @${DOCKER_COMPOSE} pull --ignore-pull-failures
26
+ #
27
+ # For now, we have to manage this explicitely...
28
+ @${DOCKER_COMPOSE} pull base_external ${RESOURCE_SERVICES}
29
+
30
+ setup:
31
+ @${COMPOSE_SHELL} setup
32
+
33
+ run: start-resources
34
+ @${DOCKER_COMPOSE} up ${APPLICATION_SERVICES}
35
+
36
+ start:
37
+ @${DOCKER_COMPOSE} up -d ${RESOURCE_SERVICES} ${APPLICATION_SERVICES}
38
+
39
+ # Send a sigterm before compose stop to get them just to shut down.
40
+ # Remove that if you want more graceful shutdowns of the application.
41
+ stop:
42
+ @${DOCKER_COMPOSE} kill -s SIGTERM ${APPLICATION_SERVICES}
43
+ @${DOCKER_COMPOSE} stop ${APPLICATION_SERVICES}
44
+
45
+ start-resources:
46
+ @if [ ! -z ${RESOURCE_SERVICES} ] ; then ${DOCKER_COMPOSE} up -d ${RESOURCE_SERVICES}; fi
47
+
48
+ stop-resources:
49
+ @${DOCKER_COMPOSE} stop
50
+
51
+ shell:
52
+ @${COMPOSE_SHELL}
53
+
54
+ test:
55
+ @${COMPOSE_SHELL} "test"
56
+
57
+ implode:
58
+ @${DOCKER_COMPOSE} down --volumes --rmi all
59
+
60
+ # Delete the application containers
61
+ rm-application:
62
+ @${DOCKER_COMPOSE} rm -f ${APPLICATION_SERVICES}
63
+
64
+ production:
65
+ @${DOCKER_COMPOSE} build base
66
+ @echo "Your image is ready and tagged as <%= options[:project_name] %>_base:latest"
67
+
68
+ reset:
69
+ @echo "Fully resetting the environment"
70
+ $(MAKE) implode
71
+ $(MAKE) initialize
File without changes
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ cmd=$1; shift
5
+
6
+ case "$cmd" in
7
+ shell)
8
+ exec "/bin/bash"
9
+ ;;
10
+ console)
11
+ # If your environment can have a console, put that target here.
12
+ echo "No console configured for <%= options[:project_name] %>"
13
+ exit 0
14
+ ;;
15
+ pass)
16
+ echo "Containter starts."
17
+ exit 0
18
+ ;;
19
+ cmd)
20
+ echo "$@"
21
+ exec /bin/bash -c "$*"
22
+ ;;
23
+ setup)
24
+ echo "This environment has no setup steps"
25
+ exit 0
26
+ ;;
27
+ <%- options[:components].each do |component| -%>
28
+ <%= component %>)
29
+ # Put this components start command here.
30
+ echo "No start command for <%= component %>"
31
+ exit 0
32
+ ;;
33
+ <%- end -%>
34
+ *)
35
+ echo "Please pass a valid command. You passed '$cmd', which is invald."
36
+ exit 3
37
+ esac
@@ -0,0 +1,59 @@
1
+ ---
2
+ version: '2'
3
+ <%- development_image = "#{options[:project_name]}_base_development:latest" -%>
4
+
5
+ services:
6
+ base_external:
7
+ image: <%= options[:base] %>
8
+
9
+ base:
10
+ build:
11
+ dockerfile: Dockerfile
12
+ context: ./
13
+ command:
14
+ - pass
15
+
16
+ base_development:
17
+ build:
18
+ dockerfile: Dockerfile.development
19
+ context: ./
20
+ command:
21
+ - pass
22
+
23
+ shell:
24
+ image: <%= development_image %>
25
+ command:
26
+ - shell
27
+ volumes: &std_volumes
28
+ - ".:/src"
29
+ <%- unless options[:resources].empty? -%>
30
+ depends_on: &std_depends
31
+ <%- options[:resources].each do |resource| -%>
32
+ - <%= resource[:name] %>
33
+ <%- end -%>
34
+ <%- end -%>
35
+
36
+ <%- options[:components].each do |component| -%>
37
+ <%= component %>:
38
+ image: <%= development_image %>
39
+ command:
40
+ - <%= component %>
41
+ # You may want additional arguments here.
42
+ volumes: *std_volumes
43
+ <%- unless options[:resources].empty? -%>
44
+ depends_on: *std_depends
45
+ <%- end -%>
46
+ <%- end -%>
47
+
48
+ <%- unless options[:resources].empty? -%>
49
+ # You'll almost certanily need to heavily modify any external resource images
50
+ # that you use.
51
+ <%- end -%>
52
+ <%- options[:resources].each do |resource| -%>
53
+ <%= resource[:name] %>:
54
+ image: <%= resource[:image] %>
55
+ # volumes:
56
+ # - Do you need to mount a config dir?
57
+ # ports:
58
+ # - Do you need to expose any ports to the host?
59
+ <%- end -%>
@@ -0,0 +1,3 @@
1
+ module Composify
2
+ VERSION = "0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: composify
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Brett Nakashima
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: trollop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.1'
41
+ description: Docker development project generator
42
+ email:
43
+ - brettnak@gmail.com
44
+ executables:
45
+ - composify
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - "./bin/composify"
50
+ - "./lib/composify.rb"
51
+ - "./lib/templates/Dockerfile.development.erb"
52
+ - "./lib/templates/Dockerfile.erb"
53
+ - "./lib/templates/Makefile.erb"
54
+ - "./lib/templates/Makefile.internal.erb"
55
+ - "./lib/templates/bin/entrypoint.sh.erb"
56
+ - "./lib/templates/docker-compose.yml.erb"
57
+ - "./lib/version.rb"
58
+ - README.md
59
+ - bin/composify
60
+ - composify.gemspec
61
+ homepage: http://gitlab.com/brettnak/mocker
62
+ licenses:
63
+ - MIT
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib/
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.6.11
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: A config generation library to generate a few Dockerfiles, Makefile, and
85
+ docker-compose.yml file that will get everything setup for local docker development. Specifically
86
+ meant for use with non-trivial development setups.
87
+ test_files: []