dockistrano 0.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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +101 -0
- data/Rakefile +1 -0
- data/bin/doc +13 -0
- data/bin/docker +0 -0
- data/dockistrano.gemspec +32 -0
- data/lib/dockistrano/cli.rb +220 -0
- data/lib/dockistrano/command_line.rb +28 -0
- data/lib/dockistrano/docker.rb +188 -0
- data/lib/dockistrano/git.rb +27 -0
- data/lib/dockistrano/hipache.rb +62 -0
- data/lib/dockistrano/registry.rb +48 -0
- data/lib/dockistrano/service.rb +331 -0
- data/lib/dockistrano/service_dependency.rb +114 -0
- data/lib/dockistrano/version.rb +3 -0
- data/lib/dockistrano.rb +14 -0
- data/spec/dockistrano/cli_spec.rb +296 -0
- data/spec/dockistrano/command_line_spec.rb +27 -0
- data/spec/dockistrano/docker_spec.rb +242 -0
- data/spec/dockistrano/git_spec.rb +48 -0
- data/spec/dockistrano/hipache_spec.rb +81 -0
- data/spec/dockistrano/registry_spec.rb +56 -0
- data/spec/dockistrano/service_dependency_spec.rb +154 -0
- data/spec/dockistrano/service_spec.rb +536 -0
- data/spec/fixtures/project_1/Dockerfile +0 -0
- data/spec/fixtures/project_1/config/dockistrano.yml +8 -0
- data/spec/spec_helper.rb +21 -0
- metadata +242 -0
| @@ -0,0 +1,296 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Dockistrano::Cli do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              let(:service) { double(registry: "registry.provider.tld", image_name: "application", tag: "develop", volumes: [], backing_services: { "postgresql" => backing_service }, environment_variables: {}, newer_version_available?: false, stop: nil) }
         | 
| 6 | 
            +
              let(:backing_service) { double(full_image_name: "registry.provider.tld/postgresql:develop", image_name: "postgresql", running?: false, newer_version_available?: false, start: nil, stop: nil) }
         | 
| 7 | 
            +
              let(:hipache) { double }
         | 
| 8 | 
            +
              let(:output) { capture(:stdout) { described_class.start(command) } }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              before do
         | 
| 11 | 
            +
                allow(Dockistrano::Service).to receive(:factory).and_return(service)
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              context "doc status" do
         | 
| 15 | 
            +
                let(:command) { ["status"] }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                it "prints the DOCKISTRANO_ENVIRONMENT" do
         | 
| 18 | 
            +
                  expect(output).to include("DOCKISTRANO_ENVIRONMENT: default")
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                it "prints the DOCKER_HOST_IP" do
         | 
| 22 | 
            +
                  expect(output).to include("DOCKER_HOST_IP: 127.0.0.1")
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                it "prints the DOCKER_BINARY" do
         | 
| 26 | 
            +
                  expect(output).to include("DOCKER_BINARY:")
         | 
| 27 | 
            +
                  expect(output).to include("bin/docker")
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                it "prints the registry" do
         | 
| 31 | 
            +
                  expect(output).to include("registry: #{service.registry}")
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                it "prints the name of the image" do
         | 
| 35 | 
            +
                  expect(output).to include("image name: #{service.image_name}")
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                it "prints the tag" do
         | 
| 39 | 
            +
                  expect(output).to include("tag: #{service.tag}")
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                it "lists all dependencies" do
         | 
| 43 | 
            +
                  expect(output).to include(backing_service.full_image_name)
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                it "lists environment variables" do
         | 
| 47 | 
            +
                  allow(service).to receive(:environment_variables).and_return({ "VARIABLE" => "value"} )
         | 
| 48 | 
            +
                  expect(output).to include("VARIABLE=value")
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                it "lists the Hipache configuration" do
         | 
| 52 | 
            +
                  allow(Dockistrano::Hipache).to receive(:new).with("127.0.0.1").and_return(hipache)
         | 
| 53 | 
            +
                  allow(hipache).to receive(:status).and_return({ "somehostname.dev" => ["127.0.0.1:1000", "23.45.56.75:1234"] })
         | 
| 54 | 
            +
                  expect(output).to include("somehostname.dev: 127.0.0.1:1000, 23.45.56.75:1234")
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              context "doc build" do
         | 
| 59 | 
            +
                let(:command) { ["build"] }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                it "builds a container" do
         | 
| 62 | 
            +
                  expect(service).to receive(:build).and_return(true)
         | 
| 63 | 
            +
                  expect(service).to receive(:test).and_return(true)
         | 
| 64 | 
            +
                  expect(service).to receive(:push).and_return(true)
         | 
| 65 | 
            +
                  expect(output).to include("built")
         | 
| 66 | 
            +
                  expect(output).to include("tests")
         | 
| 67 | 
            +
                  expect(output).to include("pushed")
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                it "doesn't run the tests and push when building failed" do
         | 
| 71 | 
            +
                  expect(service).to receive(:build).and_return(false)
         | 
| 72 | 
            +
                  expect(service).to_not receive(:test)
         | 
| 73 | 
            +
                  expect(service).to_not receive(:push)
         | 
| 74 | 
            +
                  expect { output }.to raise_error(SystemExit)
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                it "doesn't push when tests failed" do
         | 
| 78 | 
            +
                  expect(service).to receive(:build).and_return(true)
         | 
| 79 | 
            +
                  expect(service).to receive(:test).and_return(false)
         | 
| 80 | 
            +
                  expect(service).to_not receive(:push)
         | 
| 81 | 
            +
                  expect { output }.to raise_error(SystemExit)
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              context "doc pull" do
         | 
| 86 | 
            +
                let(:command) { ["pull"] }
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                it "pulls a backing service when newer versions are available" do
         | 
| 89 | 
            +
                  expect(backing_service).to receive(:newer_version_available?).and_return(true)
         | 
| 90 | 
            +
                  expect(backing_service).to receive(:pull)
         | 
| 91 | 
            +
                  expect(output).to include("Pulled")
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                it "doesn't pull a service when no new versions are available" do
         | 
| 95 | 
            +
                  expect(backing_service).to receive(:newer_version_available?).and_return(false)
         | 
| 96 | 
            +
                  expect(backing_service).to_not receive(:pull)
         | 
| 97 | 
            +
                  expect(output).to include("Uptodate")
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                it "pulls the application container when newer versions are available" do
         | 
| 101 | 
            +
                  expect(service).to receive(:newer_version_available?).and_return(true)
         | 
| 102 | 
            +
                  expect(service).to receive(:pull)
         | 
| 103 | 
            +
                  expect(output).to include("Pulled")
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                it "doesn't pull the application container when no newer versions are available" do
         | 
| 107 | 
            +
                  expect(service).to receive(:newer_version_available?).and_return(false)
         | 
| 108 | 
            +
                  expect(service).to_not receive(:pull)
         | 
| 109 | 
            +
                  expect(output).to include("Uptodate")
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
              end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
              context "doc push" do
         | 
| 114 | 
            +
                it "pushes the current container" do
         | 
| 115 | 
            +
                  expect(service).to receive(:push)
         | 
| 116 | 
            +
                  described_class.start(["push"])
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
              end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
              context "doc start-services" do
         | 
| 121 | 
            +
                let(:command) { ["start-services"] }
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                it "starts a backing service when it is not running" do
         | 
| 124 | 
            +
                  expect(backing_service).to receive(:running?).and_return(false)
         | 
| 125 | 
            +
                  expect(backing_service).to receive(:start)
         | 
| 126 | 
            +
                  expect(output).to include("Started")
         | 
| 127 | 
            +
                end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                it "does nothing when a backing services is already running" do
         | 
| 130 | 
            +
                  expect(backing_service).to receive(:running?).and_return(true)
         | 
| 131 | 
            +
                  expect(backing_service).to_not receive(:start)
         | 
| 132 | 
            +
                  expect(output).to include("Running")
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
              end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
              context "doc stop-all" do
         | 
| 137 | 
            +
                let(:command) { ["stop-all"] }
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                it "stops the current container" do
         | 
| 140 | 
            +
                  expect(service).to receive(:stop)
         | 
| 141 | 
            +
                  expect(output).to include("Stopped")
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                it "stops all backing services" do
         | 
| 145 | 
            +
                  expect(backing_service).to receive(:running?).and_return(true)
         | 
| 146 | 
            +
                  expect(backing_service).to receive(:stop)
         | 
| 147 | 
            +
                  expect(output).to include("Stopped")
         | 
| 148 | 
            +
                end
         | 
| 149 | 
            +
              end
         | 
| 150 | 
            +
             | 
| 151 | 
            +
              context "doc start" do
         | 
| 152 | 
            +
                let(:command) { ["start"] }
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                it "starts the services when not running" do
         | 
| 155 | 
            +
                  expect(service).to receive(:running?).and_return(false)
         | 
| 156 | 
            +
                  expect(service).to receive(:start)
         | 
| 157 | 
            +
                  expect(output).to include("Started")
         | 
| 158 | 
            +
                end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                it "doesn't start the services when already running" do
         | 
| 161 | 
            +
                  expect(service).to receive(:running?).and_return(true)
         | 
| 162 | 
            +
                  expect(service).to_not receive(:start)
         | 
| 163 | 
            +
                  expect(output).to include("Running")
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                it "prints an error when environment variables are missing" do
         | 
| 167 | 
            +
                  expect(service).to receive(:running?).and_return(false)
         | 
| 168 | 
            +
                  expect(service).to receive(:start).and_raise(Dockistrano::Service::EnvironmentVariablesMissing.new("error message"))
         | 
| 169 | 
            +
                  expect(output).to include("error message")
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
              end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
              context "doc stop" do
         | 
| 174 | 
            +
                let(:command) { ["stop"] }
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                it "stops the current container" do
         | 
| 177 | 
            +
                  expect(service).to receive(:stop)
         | 
| 178 | 
            +
                  expect(output).to include("Stopped")
         | 
| 179 | 
            +
                end
         | 
| 180 | 
            +
              end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
              context "doc stop ID" do
         | 
| 183 | 
            +
                let(:command) { ["stop", "123456789"] }
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                it "stops the container with the id" do
         | 
| 186 | 
            +
                  expect(Dockistrano::Docker).to receive(:stop).with("123456789")
         | 
| 187 | 
            +
                  expect(output).to include("Stopped")
         | 
| 188 | 
            +
                end
         | 
| 189 | 
            +
              end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
              context "doc restart" do
         | 
| 192 | 
            +
                let(:command) { ["restart"] }
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                it "restarts the current container" do
         | 
| 195 | 
            +
                  expect(service).to receive(:stop)
         | 
| 196 | 
            +
                  expect(service).to receive(:start)
         | 
| 197 | 
            +
                  expect(output).to include("Stopped")
         | 
| 198 | 
            +
                  expect(output).to include("Started")
         | 
| 199 | 
            +
                end
         | 
| 200 | 
            +
              end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
              context "doc exec COMMAND" do
         | 
| 203 | 
            +
                let(:command) { ["exec", "bin/rspec", "-t", "spec/models/my_model_spec.rb"] }
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                it "executes the command in the container" do
         | 
| 206 | 
            +
                  expect(service).to receive(:exec).with("bin/rspec -t spec/models/my_model_spec.rb", { "environment" => "default" })
         | 
| 207 | 
            +
                  output
         | 
| 208 | 
            +
                end
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                it "prints an error when environment variables are missing" do
         | 
| 211 | 
            +
                  expect(service).to receive(:exec).and_raise(Dockistrano::Service::EnvironmentVariablesMissing.new("error message"))
         | 
| 212 | 
            +
                  expect(output).to include("error message")
         | 
| 213 | 
            +
                end
         | 
| 214 | 
            +
              end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
              context "doc console" do
         | 
| 217 | 
            +
                let(:command) { ["console"] }
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                it "starts a bash console in the container" do
         | 
| 220 | 
            +
                  expect(service).to receive(:console).with("/bin/bash", { "environment" => "default" })
         | 
| 221 | 
            +
                  output
         | 
| 222 | 
            +
                end
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                it "prints an error when environment variables are missing" do
         | 
| 225 | 
            +
                  expect(service).to receive(:console).and_raise(Dockistrano::Service::EnvironmentVariablesMissing.new("error message"))
         | 
| 226 | 
            +
                  expect(output).to include("error message")
         | 
| 227 | 
            +
                end
         | 
| 228 | 
            +
              end
         | 
| 229 | 
            +
             | 
| 230 | 
            +
              context "doc console COMMAND" do
         | 
| 231 | 
            +
                let(:command) { ["console", "bin/rails console"] }
         | 
| 232 | 
            +
             | 
| 233 | 
            +
                it "starts a console in the container" do
         | 
| 234 | 
            +
                  expect(service).to receive(:console).with("bin/rails console", { "environment" => "default" })
         | 
| 235 | 
            +
                  output
         | 
| 236 | 
            +
                end
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                it "prints an error when environment variables are missing" do
         | 
| 239 | 
            +
                  expect(service).to receive(:console).and_raise(Dockistrano::Service::EnvironmentVariablesMissing.new("error message"))
         | 
| 240 | 
            +
                  expect(output).to include("error message")
         | 
| 241 | 
            +
                end
         | 
| 242 | 
            +
              end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
              context "doc clean" do
         | 
| 245 | 
            +
                let(:command) { ["clean"] }
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                it "cleans the Docker instance and service dependency cache" do
         | 
| 248 | 
            +
                  expect(Dockistrano::Docker).to receive(:clean)
         | 
| 249 | 
            +
                  expect(Dockistrano::ServiceDependency).to receive(:clear_cache)
         | 
| 250 | 
            +
                  output
         | 
| 251 | 
            +
                end
         | 
| 252 | 
            +
              end
         | 
| 253 | 
            +
             | 
| 254 | 
            +
              context "doc logs" do
         | 
| 255 | 
            +
                let(:command) { ["logs"] }
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                it "attaches to the containers output when the container is running" do
         | 
| 258 | 
            +
                  expect(service).to receive(:running?).and_return(true)
         | 
| 259 | 
            +
                  expect(service).to receive(:attach)
         | 
| 260 | 
            +
                  expect(output).to include("Container application running, attaching to output")
         | 
| 261 | 
            +
                end
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                it "prints the logs of the last run" do
         | 
| 264 | 
            +
                  expect(service).to receive(:running?).and_return(false)
         | 
| 265 | 
            +
                  expect(service).to receive(:logs)
         | 
| 266 | 
            +
                  expect(output).to include("Container application stopped, printing logs of last run")
         | 
| 267 | 
            +
                end
         | 
| 268 | 
            +
              end
         | 
| 269 | 
            +
             | 
| 270 | 
            +
              context "doc logs NAME" do
         | 
| 271 | 
            +
                let(:command) { ["logs", "postgresql"] }
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                it "attaches to the containers output when the container is running" do
         | 
| 274 | 
            +
                  expect(backing_service).to receive(:running?).and_return(true)
         | 
| 275 | 
            +
                  expect(backing_service).to receive(:attach)
         | 
| 276 | 
            +
                  expect(output).to include("Container postgresql running, attaching to output")
         | 
| 277 | 
            +
                end
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                it "prints the logs of the last run" do
         | 
| 280 | 
            +
                  expect(backing_service).to receive(:running?).and_return(false)
         | 
| 281 | 
            +
                  expect(backing_service).to receive(:logs)
         | 
| 282 | 
            +
                  expect(output).to include("Container postgresql stopped, printing logs of last run")
         | 
| 283 | 
            +
                end
         | 
| 284 | 
            +
              end
         | 
| 285 | 
            +
             | 
| 286 | 
            +
              context "doc ALIAS ARGUMENTS" do
         | 
| 287 | 
            +
                let(:command) { ["rspec", "spec/models/my_model_spec.rb"] }
         | 
| 288 | 
            +
             | 
| 289 | 
            +
                it "executes aliases that are defined in the configuration" do
         | 
| 290 | 
            +
                  allow(service).to receive(:config).and_return({ "aliases" => { "rspec" => "exec -e test bin/rspec" } })
         | 
| 291 | 
            +
                  expect(Kernel).to receive(:exec).with("doc exec -e test bin/rspec spec/models/my_model_spec.rb")
         | 
| 292 | 
            +
                  output
         | 
| 293 | 
            +
                end
         | 
| 294 | 
            +
              end
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Dockistrano::CommandLine do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { described_class }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              context ".command_with_result" do
         | 
| 8 | 
            +
                it "executes the command and returns a string with the result" do
         | 
| 9 | 
            +
                  expect(described_class.command_with_result("date")).to eq(`date`)
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              context ".command_with_stream" do
         | 
| 14 | 
            +
                it "executes the command and returns a stream of output" do
         | 
| 15 | 
            +
                  expect(Kernel).to receive(:system).with("date").and_return(true)
         | 
| 16 | 
            +
                  expect(described_class.command_with_stream("date")).to be_true
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              context ".command_with_interaction" do
         | 
| 21 | 
            +
                it "executes the command and returns a stream of output" do
         | 
| 22 | 
            +
                  expect(Kernel).to receive(:exec).with("date").and_return(true)
         | 
| 23 | 
            +
                  expect(described_class.command_with_interaction("date")).to be_true
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,242 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Dockistrano::Docker do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { described_class }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              before do
         | 
| 8 | 
            +
                ENV["DOCKER_BINARY"] = "docker"
         | 
| 9 | 
            +
                ENV["DOCKER_HOST_IP"] = "127.0.0.1"
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              context ".docker_command" do
         | 
| 13 | 
            +
                it "returns a string that allows us to call docker" do
         | 
| 14 | 
            +
                  ENV["DOCKER_BINARY"] = "/bin/docker"
         | 
| 15 | 
            +
                  ENV["DOCKER_HOST_IP"] = "127.0.0.1"
         | 
| 16 | 
            +
                  expect(subject.docker_command).to eq("/bin/docker -H 127.0.0.1")
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                it "raises an error when DOCKER_BINARY is not set" do
         | 
| 20 | 
            +
                  ENV["DOCKER_BINARY"] = nil
         | 
| 21 | 
            +
                  ENV["DOCKER_HOST_IP"] = "127.0.0.1"
         | 
| 22 | 
            +
                  expect { subject.docker_command }.to raise_error(Dockistrano::Docker::EnvironmentVariableMissing, /DOCKER_BINARY/)
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                it "raises an error when DOCKER_BINARY is not set" do
         | 
| 26 | 
            +
                  ENV["DOCKER_BINARY"] = "/bin/docker"
         | 
| 27 | 
            +
                  ENV["DOCKER_HOST_IP"] = nil
         | 
| 28 | 
            +
                  expect { subject.docker_command }.to raise_error(Dockistrano::Docker::EnvironmentVariableMissing, /DOCKER_HOST_IP/)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              context ".ps" do
         | 
| 33 | 
            +
                it "calls docker with the ps command" do
         | 
| 34 | 
            +
                  expect(subject).to receive(:execute).with(["ps", {}])
         | 
| 35 | 
            +
                  subject.ps
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              context ".stop" do
         | 
| 40 | 
            +
                it "stops the container" do
         | 
| 41 | 
            +
                  expect(subject).to receive(:execute).with(["stop", "123456789"])
         | 
| 42 | 
            +
                  subject.stop("123456789")
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              context ".run" do
         | 
| 47 | 
            +
                it "runs the default command when no command is given" do
         | 
| 48 | 
            +
                  expect(subject).to receive(:execute).with(["run", {e: "VAR=value"}, "registry/image:tag"])
         | 
| 49 | 
            +
                  subject.run("registry/image:tag", e: "VAR=value")
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                it "runs the default command when no command is given" do
         | 
| 53 | 
            +
                  expect(subject).to receive(:execute).with(["run", {e: "VAR=value"}, "registry/image:tag", "echo 'foobar'"])
         | 
| 54 | 
            +
                  subject.run("registry/image:tag", e: "VAR=value", command: "echo 'foobar'")
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              context ".exec" do
         | 
| 59 | 
            +
                it "runs the default command when no command is given" do
         | 
| 60 | 
            +
                  expect(subject).to receive(:execute).with(["run", {e: "VAR=value"}, "registry/image:tag"], :stream)
         | 
| 61 | 
            +
                  subject.exec("registry/image:tag", e: "VAR=value")
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                it "runs the default command when no command is given" do
         | 
| 65 | 
            +
                  expect(subject).to receive(:execute).with(["run", {e: "VAR=value"}, "registry/image:tag", "echo 'foobar'"], :stream)
         | 
| 66 | 
            +
                  subject.exec("registry/image:tag", e: "VAR=value", command: "echo 'foobar'")
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              context ".console" do
         | 
| 71 | 
            +
                it "runs the default command when no command is given" do
         | 
| 72 | 
            +
                  expect(subject).to receive(:execute).with(["run", { "e" => "VAR=value", "t" => true, "i" => true }, "registry/image:tag"], :interaction)
         | 
| 73 | 
            +
                  subject.console("registry/image:tag", "e" => "VAR=value")
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                it "runs the default command when no command is given" do
         | 
| 77 | 
            +
                  expect(subject).to receive(:execute).with(["run", { "e" => "VAR=value", "t" => true, "i" => true}, "registry/image:tag", "echo 'foobar'"], :interaction)
         | 
| 78 | 
            +
                  subject.console("registry/image:tag", "e" => "VAR=value", command: "echo 'foobar'")
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
              context ".execute" do
         | 
| 83 | 
            +
                it "calls docker and returns the result" do
         | 
| 84 | 
            +
                  expect(Dockistrano::CommandLine).to receive(:command_with_result).with("docker -H 127.0.0.1 version")
         | 
| 85 | 
            +
                  subject.execute(["version"])
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                it "adds options to the command" do
         | 
| 89 | 
            +
                  expect(Dockistrano::CommandLine).to receive(:command_with_result).with("docker -H 127.0.0.1 version -a")
         | 
| 90 | 
            +
                  subject.execute(["version", { a: true }])
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                it "adds array options to the command" do
         | 
| 94 | 
            +
                  expect(Dockistrano::CommandLine).to receive(:command_with_result).with("docker -H 127.0.0.1 version -a b -a c")
         | 
| 95 | 
            +
                  subject.execute(["version", { a: ["b", "c"] }])
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                it "calls docker and stream to stdout" do
         | 
| 99 | 
            +
                  expect(Dockistrano::CommandLine).to receive(:command_with_stream).with("docker -H 127.0.0.1 version")
         | 
| 100 | 
            +
                  subject.execute(["version"], :stream)
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                it "calls docker and takes over the console" do
         | 
| 104 | 
            +
                  expect(Dockistrano::CommandLine).to receive(:command_with_interaction).with("docker -H 127.0.0.1 version")
         | 
| 105 | 
            +
                  subject.execute(["version"], :interaction)
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
              context ".running_container_id" do
         | 
| 110 | 
            +
                it "returns the first id of a running container matching with the image name" do
         | 
| 111 | 
            +
                  stub_request(:get, "http://127.0.0.1:4243/containers/json").to_return(status: 200, body: '[{"Id":"8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider webserver","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49225,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
         | 
| 112 | 
            +
                    {"Id":"107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider worker","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49224,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
         | 
| 113 | 
            +
                    {"Id":"066474c539231e445c636dd6ef2879e6a3e304cead10f78bd79e385b161cbdf5","Image":"registry.dev.provider.net/hipache:develop","Command":"supervisord -n","Created":1382447352,"Status":"Up 24 hours","Ports":[{"PrivatePort":80,"PublicPort":80,"Type":"tcp"},{"PrivatePort":6379,"PublicPort":16379,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0}]')
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  expect(subject.running_container_id("registry.dev.provider.net/provider-app-2.0:develop")).to eq("8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36")
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
              end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
              context ".last_run_container_id" do
         | 
| 120 | 
            +
                it "returns the id of the previous run of the container" do
         | 
| 121 | 
            +
                  stub_request(:get, "http://127.0.0.1:4243/containers/json?all=1").to_return(status: 200, body: '[{"Id":"8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"cat /dockistrano.yml","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49225,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
         | 
| 122 | 
            +
                    {"Id":"107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider worker","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49224,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
         | 
| 123 | 
            +
                    {"Id":"066474c539231e445c636dd6ef2879e6a3e304cead10f78bd79e385b161cbdf5","Image":"registry.dev.provider.net/hipache:develop","Command":"supervisord -n","Created":1382447352,"Status":"Up 24 hours","Ports":[{"PrivatePort":80,"PublicPort":80,"Type":"tcp"},{"PrivatePort":6379,"PublicPort":16379,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0}]')
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                  expect(subject.last_run_container_id("registry.dev.provider.net/provider-app-2.0:develop")).to eq("107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a")
         | 
| 126 | 
            +
                end
         | 
| 127 | 
            +
              end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
              context ".image_id" do
         | 
| 130 | 
            +
                it "returns the id of the image with the given name" do
         | 
| 131 | 
            +
                  expect(subject).to receive(:inspect_image).and_return({ "id" => "123456789" })
         | 
| 132 | 
            +
                  expect(subject.image_id("registry.dev/application:tag")).to eq("123456789")
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
              end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
              context ".inspect_image" do
         | 
| 137 | 
            +
                it "returns information about the image" do
         | 
| 138 | 
            +
                  stub_request(:get, "http://127.0.0.1:4243/images/123456789/json").to_return({
         | 
| 139 | 
            +
                    status: 200,
         | 
| 140 | 
            +
                    body: '{"id":"49f387cc90f2d5b82ded91c239b6e583f8b955cb532912cc959b1d1289b3f8f1","parent":"7735e8f30a47f02aa46732e864879fad0fb0b74230f7695b6235d6faf766dcb2","created":"2013-10-21T16:03:17.191097983+02:00","container":"5c2c523d3561d205f5459925325890bbf8054010cd908f61feed3e76520dcf54","container_config":{},"docker_version":"0.6.3","config":{},"architecture":"x86_64","Size":12288}'
         | 
| 141 | 
            +
                  })
         | 
| 142 | 
            +
                  expect(subject.inspect_image("123456789")).to include('id')
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                it "raises an error when the image is not found" do
         | 
| 146 | 
            +
                  stub_request(:get, "http://127.0.0.1:4243/images/123456789/json").to_return({
         | 
| 147 | 
            +
                    status: 404,
         | 
| 148 | 
            +
                    body: 'No such image: 123456789'
         | 
| 149 | 
            +
                  })
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                  expect { subject.inspect_image("123456789") }.to raise_error(Dockistrano::Docker::ImageNotFound, /No such image: 123456789/)
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
              end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
              context ".build" do
         | 
| 156 | 
            +
                it "builds the container" do
         | 
| 157 | 
            +
                  expect(subject).to receive(:execute).with(["build", {t: "full_image_name"}, "."], :stream)
         | 
| 158 | 
            +
                  subject.build("full_image_name")
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
              end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
              context ".pull" do
         | 
| 163 | 
            +
                it "pulls the container with Docker" do
         | 
| 164 | 
            +
                  expect(subject).to receive(:execute).with(["pull", { t: "tag" }, "full_image_name"])
         | 
| 165 | 
            +
                  subject.pull("full_image_name", "tag")
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
              end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
              context ".push" do
         | 
| 170 | 
            +
                it "pushes the container with Docker" do
         | 
| 171 | 
            +
                  expect(subject).to receive(:execute).with(["push", "full_image_name", "tag"], :stream)
         | 
| 172 | 
            +
                  subject.push("full_image_name", "tag")
         | 
| 173 | 
            +
                end
         | 
| 174 | 
            +
              end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
              context ".logs" do
         | 
| 177 | 
            +
                it "returns the logs for the container" do
         | 
| 178 | 
            +
                  expect(subject).to receive(:execute).with(["logs", "72819312"], :stream)
         | 
| 179 | 
            +
                  subject.logs("72819312")
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
              end
         | 
| 182 | 
            +
             | 
| 183 | 
            +
              context ".attach" do
         | 
| 184 | 
            +
                it "attaches to the containers output" do
         | 
| 185 | 
            +
                  expect(subject).to receive(:execute).with(["attach", "72819312"], :stream)
         | 
| 186 | 
            +
                  subject.attach("72819312")
         | 
| 187 | 
            +
                end
         | 
| 188 | 
            +
              end
         | 
| 189 | 
            +
             | 
| 190 | 
            +
              context ".inspect_container" do
         | 
| 191 | 
            +
                it "returns information about the container" do
         | 
| 192 | 
            +
                  stub_request(:get, 'http://127.0.0.1:4243/containers/123456789/json').to_return({
         | 
| 193 | 
            +
                    status: 200,
         | 
| 194 | 
            +
                    body: '{"ID":"8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36","Created":"2013-10-22T15:43:00.213138644+02:00"}'
         | 
| 195 | 
            +
                  })
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                  expect(subject.inspect_container("123456789")).to include("ID")
         | 
| 198 | 
            +
                end
         | 
| 199 | 
            +
              end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
              context ".clean" do
         | 
| 202 | 
            +
                before do
         | 
| 203 | 
            +
                  allow(Dockistrano::CommandLine).to receive(:command_with_stream)
         | 
| 204 | 
            +
                  allow(subject).to receive(:docker_command).and_return("docker")
         | 
| 205 | 
            +
                end
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                it "cleans images from the docker instance" do
         | 
| 208 | 
            +
                  expect(Dockistrano::CommandLine).to receive(:command_with_stream).with("docker rmi $(docker images -a | grep \"^<none>\" | awk '{print $3}')")
         | 
| 209 | 
            +
                  subject.clean
         | 
| 210 | 
            +
                end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                it "cleans containers from the docker instance" do
         | 
| 213 | 
            +
                  expect(Dockistrano::CommandLine).to receive(:command_with_stream).with("docker rm $(docker ps -a -q)")
         | 
| 214 | 
            +
                  subject.clean
         | 
| 215 | 
            +
                end
         | 
| 216 | 
            +
              end
         | 
| 217 | 
            +
             | 
| 218 | 
            +
              context ".stop_all_containers_from_image" do
         | 
| 219 | 
            +
                it "stops all containers from an image" do
         | 
| 220 | 
            +
                  stub_request(:get, "http://127.0.0.1:4243/containers/json").to_return(status: 200, body: '[{"Id":"8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider webserver","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49225,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
         | 
| 221 | 
            +
                    {"Id":"107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a","Image":"registry.dev.provider.net/provider-app-2.0:develop","Command":"bin/provider worker","Created":1382449380,"Status":"Up 24 hours","Ports":[{"PrivatePort":3000,"PublicPort":49224,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0},
         | 
| 222 | 
            +
                    {"Id":"066474c539231e445c636dd6ef2879e6a3e304cead10f78bd79e385b161cbdf5","Image":"registry.dev.provider.net/hipache:develop","Command":"supervisord -n","Created":1382447352,"Status":"Up 24 hours","Ports":[{"PrivatePort":80,"PublicPort":80,"Type":"tcp"},{"PrivatePort":6379,"PublicPort":16379,"Type":"tcp"}],"SizeRw":0,"SizeRootFs":0}]')
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                  expect(subject).to receive(:execute).with(["stop", "8e319853f561ba2c22de2ec9ff2584f99d091dd20cc5b393ab874631c6993a36"])
         | 
| 225 | 
            +
                  expect(subject).to receive(:execute).with(["stop", "107fc12c1c4b8e42091bd46e97c985d42c9e0d06506327e84f28fef585f9865a"])
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                  subject.stop_all_containers_from_image("registry.dev.provider.net/provider-app-2.0:develop")
         | 
| 228 | 
            +
                end
         | 
| 229 | 
            +
              end
         | 
| 230 | 
            +
             | 
| 231 | 
            +
              context ".tags_for_image" do
         | 
| 232 | 
            +
                it "returns a list of tags for an image" do
         | 
| 233 | 
            +
                  stub_request(:get, "http://127.0.0.1:4243/images/json").to_return({
         | 
| 234 | 
            +
                    status: 200,
         | 
| 235 | 
            +
                    body: '[{"Repository":"registry.provider.net/application","Tag":"develop"},{"Repository":"registry.provider.net/application","Tag":"latest"},{"Repository":"registry.provider.net/memcached","Tag":"develop"}]'
         | 
| 236 | 
            +
                  })
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                  expect(subject.tags_for_image("registry.provider.net/application")).to eq(["develop", "latest"])
         | 
| 239 | 
            +
                end
         | 
| 240 | 
            +
              end
         | 
| 241 | 
            +
             | 
| 242 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Dockistrano::Git do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              context ".repository_name" do
         | 
| 6 | 
            +
                let(:command) { double }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                it "returns the name from a ssh remote" do
         | 
| 9 | 
            +
                  expect(Cocaine::CommandLine).to receive(:new).with("git config --get remote.origin.url").and_return(command)
         | 
| 10 | 
            +
                  expect(command).to receive(:run).and_return("git@github.com:username/reponame-with-2.0.git")
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  expect(described_class.repository_name).to eq("reponame-with-2.0")
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                it "returns the name from a ssh remote ending without .git" do
         | 
| 16 | 
            +
                  expect(Cocaine::CommandLine).to receive(:new).with("git config --get remote.origin.url").and_return(command)
         | 
| 17 | 
            +
                  expect(command).to receive(:run).and_return("git@github.com:username/reponame-with-2.0")
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  expect(described_class.repository_name).to eq("reponame-with-2.0")
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                it "returns the name from a https remote" do
         | 
| 23 | 
            +
                  expect(Cocaine::CommandLine).to receive(:new).with("git config --get remote.origin.url").and_return(command)
         | 
| 24 | 
            +
                  expect(command).to receive(:run).and_return("https://github.com/username/reponame-with-2.0")
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  expect(described_class.repository_name).to eq("reponame-with-2.0")
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              context ".branch" do
         | 
| 32 | 
            +
                let(:command) { double }
         | 
| 33 | 
            +
                it "returns the name of the branch" do
         | 
| 34 | 
            +
                  expect(Cocaine::CommandLine).to receive(:new).with("git rev-parse --abbrev-ref HEAD").and_return(command)
         | 
| 35 | 
            +
                  expect(command).to receive(:run).and_return("branch_name\n")
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  expect(described_class.branch).to eq("branch_name")
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                it "returns the JANKY_BRANCH env variable when available" do
         | 
| 41 | 
            +
                  ENV["JANKY_BRANCH"] = "feature/foobar"
         | 
| 42 | 
            +
                  expect(described_class.branch).to eq("feature-foobar")
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
             | 
| 48 | 
            +
            end
         |