capistrano 3.18.1 → 3.19.0
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 +4 -4
- data/.docker/Dockerfile +7 -0
- data/.docker/ssh_key_rsa +49 -0
- data/.docker/ssh_key_rsa.pub +1 -0
- data/.docker/ubuntu_setup.sh +23 -0
- data/.github/workflows/ci.yml +1 -21
- data/.rubocop.yml +3 -3
- data/DEVELOPMENT.md +4 -13
- data/Gemfile +1 -2
- data/docker-compose.yml +8 -0
- data/features/deploy.feature +5 -1
- data/features/sshconnect.feature +1 -1
- data/features/step_definitions/assertions.rb +33 -23
- data/features/step_definitions/setup.rb +10 -13
- data/features/support/docker_gateway.rb +53 -0
- data/features/support/env.rb +0 -10
- data/features/support/remote_command_helpers.rb +3 -3
- data/features/support/remote_ssh_helpers.rb +33 -0
- data/lib/capistrano/scm/git.rb +5 -0
- data/lib/capistrano/scm/tasks/git.rake +11 -0
- data/lib/capistrano/tasks/deploy.rake +23 -1
- data/lib/capistrano/version.rb +1 -1
- data/spec/integration/dsl_spec.rb +10 -10
- data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +1 -0
- data/spec/lib/capistrano/scm/git_spec.rb +10 -0
- data/spec/support/test_app.rb +14 -11
- metadata +12 -10
- data/Dangerfile +0 -1
- data/features/support/vagrant_helpers.rb +0 -41
- data/spec/support/.gitignore +0 -1
- data/spec/support/Vagrantfile +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 394b09ce3f7d404792341024337f15b508055a5cff92fe9c3b3db0b30a195f86
|
4
|
+
data.tar.gz: 94609866fe948bfa1e7f9ded8fc76f0622fc7123733285a82ac300dc772ccbef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03eca17ed3fd4484babfee22ed9bbb6a844eb79b6141471295a6cd15fe7423b01322fc57ec9c4771e08eebfd02ac51cca9ea8fb4df230dd1104ed94c739bad6a
|
7
|
+
data.tar.gz: e622bfb56fc09785b8ca7c1cbb156c2c78348209acfe3b5ca7137d53f16a762c96e89a3a71d80f7ba9dfc29cd1c845cce69e5df8ea045da429252ce07a0dac64
|
data/.docker/Dockerfile
ADDED
data/.docker/ssh_key_rsa
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
-----BEGIN OPENSSH PRIVATE KEY-----
|
2
|
+
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
|
49
|
+
-----END OPENSSH PRIVATE KEY-----
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC6wVCoBOGYS5qfXZGiKjuh7RWExlzrQ1Gml8Z3DDCggSEibh1WXJU9+rNKTqHmVoGy36iarPfjsGWw3IbiWiMOXD7crg3BCyRbksAdrVV/MIq6BiKqnGaQvOV9AE5RbA6W4/prkEKL/tdnpVaWpMbtthEo6H/IO3Ih+iXomni4NkUBjDjJf6sr8B/vI4aIcp0I5/uXNI3zIWVhQ6yBZ4hORs8jPBMpe7jMoFb5z8t6AUUfmIc66JiLmLX2hqYEreIB7rzlPOsDsOByADubyA/r3zYaA5kZxLbHT+sgQitjb4TATdoCxX6+utxVQeRZK4YrCR3D/aWzhmOgl5OHxO7ArWgICXC18icrvDdUACxOWKRaSe0WXw0nX1L0ZteKuYsvFAf0t0nNPStnWkxzRA4snzJCiptuWcjx8p7WY0Ph267ERq9rNFgMDmSsHaYMOnJAXr8WF00zFcVgAW6b3MBJSmBEtcz45RvMDv4XiMvzZiP/1+we+JXI1f5Y8LhyVtkeME5J7u6LrNUI5bvBMyDodMkmOonRdpL4iwOUXwpETX7i8fsr7+8YFw+JtXQ0iePq4V2PmmPNXThljhkhConwVnGsfV4qfuGaGJgMKJfK/E6hF8W9ejEH9BvmX7l75fyAK0zMq+n6ohOr4M4wVcz9G+s+5vSZ5JNwYTyVrAthtw== test@example.com
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
export DEBIAN_FRONTEND=noninteractive
|
6
|
+
|
7
|
+
# Create `deployer` user
|
8
|
+
adduser --disabled-password deployer < /dev/null
|
9
|
+
mkdir -p /home/deployer/.ssh
|
10
|
+
cp /root/.ssh/authorized_keys /home/deployer/.ssh
|
11
|
+
chown -R deployer:deployer /home/deployer/.ssh
|
12
|
+
chmod 600 /home/deployer/.ssh/authorized_keys
|
13
|
+
|
14
|
+
# Install and configure sshd
|
15
|
+
apt -y update
|
16
|
+
apt-get -y install openssh-server git
|
17
|
+
{
|
18
|
+
echo "Port 22"
|
19
|
+
echo "PasswordAuthentication no"
|
20
|
+
echo "ChallengeResponseAuthentication no"
|
21
|
+
} >> /etc/ssh/sshd_config
|
22
|
+
mkdir /var/run/sshd
|
23
|
+
chmod 0755 /var/run/sshd
|
data/.github/workflows/ci.yml
CHANGED
@@ -66,31 +66,11 @@ jobs:
|
|
66
66
|
bundler-cache: true
|
67
67
|
- name: rake rubocop
|
68
68
|
run: bundle exec rake rubocop
|
69
|
-
danger:
|
70
|
-
runs-on: ubuntu-latest
|
71
|
-
steps:
|
72
|
-
- uses: actions/checkout@v4
|
73
|
-
- name: Set up Ruby
|
74
|
-
uses: ruby/setup-ruby@v1
|
75
|
-
with:
|
76
|
-
ruby-version: "ruby" # latest-stable
|
77
|
-
bundler-cache: true
|
78
|
-
- name: danger
|
79
|
-
env:
|
80
|
-
DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
|
81
|
-
run: bundle exec danger
|
82
69
|
features:
|
83
70
|
needs: [spec, spec-legacy]
|
84
|
-
runs-on:
|
71
|
+
runs-on: ubuntu-latest
|
85
72
|
steps:
|
86
73
|
- uses: actions/checkout@v4
|
87
|
-
- name: Cache Vagrant boxes
|
88
|
-
uses: actions/cache@v3
|
89
|
-
with:
|
90
|
-
path: ~/.vagrant.d/boxes
|
91
|
-
key: ${{ runner.os }}-vagrant-${{ hashFiles('Vagrantfile') }}
|
92
|
-
restore-keys: |
|
93
|
-
${{ runner.os }}-vagrant-
|
94
74
|
- name: Set up Ruby
|
95
75
|
uses: ruby/setup-ruby@v1
|
96
76
|
with:
|
data/.rubocop.yml
CHANGED
@@ -13,13 +13,13 @@ Metrics/BlockLength:
|
|
13
13
|
- "lib/**/*.rake"
|
14
14
|
Style/BarePercentLiterals:
|
15
15
|
EnforcedStyle: percent_q
|
16
|
+
Style/BracesAroundHashParameters:
|
17
|
+
Exclude:
|
18
|
+
- spec/integration/dsl_spec.rb
|
16
19
|
Style/ClassAndModuleChildren:
|
17
20
|
Enabled: false
|
18
21
|
Style/DoubleNegation:
|
19
22
|
Enabled: false
|
20
|
-
Style/FileName:
|
21
|
-
Exclude:
|
22
|
-
- "Dangerfile"
|
23
23
|
Style/IndentHeredoc:
|
24
24
|
Enabled: false
|
25
25
|
Style/SpaceAroundEqualsInParameterDefault:
|
data/DEVELOPMENT.md
CHANGED
@@ -20,22 +20,16 @@ Everyone can help improve Capistrano. There are ways to contribute even if you a
|
|
20
20
|
|
21
21
|
## Contributing documentation
|
22
22
|
|
23
|
-
Improvements and additions to Capistrano's documentation are very much appreciated. The official documentation is stored in the `docs/` directory as Markdown files. These files are used to automatically generate the [capistranorb.com](
|
23
|
+
Improvements and additions to Capistrano's documentation are very much appreciated. The official documentation is stored in the `docs/` directory as Markdown files. These files are used to automatically generate the [capistranorb.com](https://capistranorb.com/) website, which is hosted by GitHub Pages. Feel free to make changes to this documentation as you see fit. Before opening a pull request, make sure your documentation renders correctly by previewing the website in your local environment. Refer to [docs/README.md][] for instructions.
|
24
24
|
|
25
25
|
## Setting up your development environment
|
26
26
|
|
27
|
-
Capistrano is a Ruby project, so we expect you to have a functioning Ruby environment
|
28
|
-
|
29
|
-
Make sure to install:
|
30
|
-
|
31
|
-
* [Bundler](https://bundler.io/)
|
32
|
-
* [Vagrant](https://www.vagrantup.com/)
|
33
|
-
* [VirtualBox](https://www.virtualbox.org/wiki/Downloads) (or another [Vagrant-supported](https://docs.vagrantup.com/v2/getting-started/providers.html) VM host)
|
27
|
+
Capistrano is a Ruby project, so we expect you to have a functioning Ruby environment with the latest stable version of Ruby. To run Cucumber tests, you'll also need [Docker installed](https://docs.docker.com/get-docker/) and running.
|
34
28
|
|
35
29
|
|
36
30
|
### Running tests
|
37
31
|
|
38
|
-
Capistrano has two test suites: an RSpec suite and a Cucumber suite. The RSpec suite handles quick feedback unit specs. The Cucumber suite is an integration suite that uses
|
32
|
+
Capistrano has two test suites: an RSpec suite and a Cucumber suite. The RSpec suite handles quick feedback unit specs. The Cucumber suite is an integration suite that uses a Docker container as an SSH server and deployment target.
|
39
33
|
|
40
34
|
```
|
41
35
|
# Ensure all dependencies are installed
|
@@ -44,11 +38,8 @@ $ bundle install
|
|
44
38
|
# Run the RSpec suite
|
45
39
|
$ bundle exec rake spec
|
46
40
|
|
47
|
-
# Run the Cucumber suite
|
41
|
+
# Run the Cucumber suite (Docker must be running)
|
48
42
|
$ bundle exec rake features
|
49
|
-
|
50
|
-
# Run the Cucumber suite and leave the VM running (faster for subsequent runs)
|
51
|
-
$ bundle exec rake features KEEP_RUNNING=1
|
52
43
|
```
|
53
44
|
|
54
45
|
## Coding guidelines
|
data/Gemfile
CHANGED
@@ -38,10 +38,9 @@ if Gem::Requirement.new("< 2.2").satisfied_by?(Gem::Version.new(RUBY_VERSION))
|
|
38
38
|
gem "rake", "< 13.0.0"
|
39
39
|
end
|
40
40
|
|
41
|
-
# We only run
|
41
|
+
# We only run rubocop and its dependencies on a new-ish ruby; no need to install them otherwise
|
42
42
|
if Gem::Requirement.new("> 2.4").satisfied_by?(Gem::Version.new(RUBY_VERSION))
|
43
43
|
gem "base64"
|
44
|
-
gem "danger"
|
45
44
|
gem "psych", "< 4" # Ensures rubocop works on Ruby 3.1
|
46
45
|
gem "racc"
|
47
46
|
gem "rubocop", "0.48.1"
|
data/docker-compose.yml
ADDED
data/features/deploy.feature
CHANGED
@@ -40,6 +40,11 @@ Feature: Deploy
|
|
40
40
|
Then the repo is cloned
|
41
41
|
And the release is created
|
42
42
|
|
43
|
+
Scenario: REVISION and REVISION_TIME files are present
|
44
|
+
When I make 1 deployment
|
45
|
+
Then the REVISION file is created in the release
|
46
|
+
Then the REVISION_TIME file is created in the release
|
47
|
+
|
43
48
|
Scenario: Symlink linked files
|
44
49
|
When I run cap "deploy:symlink:linked_files deploy:symlink:release" as part of a release
|
45
50
|
Then file symlinks are created in the new release
|
@@ -85,4 +90,3 @@ Feature: Deploy
|
|
85
90
|
Given I make 3 deployments
|
86
91
|
When I rollback to a specific release
|
87
92
|
Then the current symlink points to that specific release
|
88
|
-
|
data/features/sshconnect.feature
CHANGED
@@ -8,4 +8,4 @@ Feature: SSH Connection
|
|
8
8
|
Scenario: Switching from default user to root and back again
|
9
9
|
When I run cap "am_i_root"
|
10
10
|
Then the task is successful
|
11
|
-
And the output matches "I am uid=0\(root\)" followed by "I am uid=\d+\(
|
11
|
+
And the output matches "I am uid=0\(root\)" followed by "I am uid=\d+\(deployer\)"
|
@@ -6,67 +6,77 @@ end
|
|
6
6
|
|
7
7
|
Then(/^git wrapper permissions are 0700$/) do
|
8
8
|
permissions_test = %Q([ $(stat -c "%a" #{TestApp.git_wrapper_path_glob}) == "700" ])
|
9
|
-
|
10
|
-
|
11
|
-
expect(status).to be_success
|
9
|
+
expect { run_remote_ssh_command(permissions_test) }.not_to raise_error
|
12
10
|
end
|
13
11
|
|
14
12
|
Then(/^the shared path is created$/) do
|
15
|
-
|
13
|
+
run_remote_ssh_command(test_dir_exists(TestApp.shared_path))
|
16
14
|
end
|
17
15
|
|
18
16
|
Then(/^the releases path is created$/) do
|
19
|
-
|
17
|
+
run_remote_ssh_command(test_dir_exists(TestApp.releases_path))
|
20
18
|
end
|
21
19
|
|
22
20
|
Then(/^(\d+) valid releases are kept/) do |num|
|
23
21
|
test = %Q([ $(ls -g #{TestApp.releases_path} | grep -E '[0-9]{14}' | wc -l) == "#{num}" ])
|
24
|
-
|
25
|
-
expect(status).to be_success
|
22
|
+
expect { run_remote_ssh_command(test) }.not_to raise_error
|
26
23
|
end
|
27
24
|
|
28
25
|
Then(/^the invalid (.+) release is ignored$/) do |filename|
|
29
26
|
test = "ls -g #{TestApp.releases_path} | grep #{filename}"
|
30
|
-
|
31
|
-
expect(status).to be_success
|
27
|
+
expect { run_remote_ssh_command(test) }.not_to raise_error
|
32
28
|
end
|
33
29
|
|
34
30
|
Then(/^directories in :linked_dirs are created in shared$/) do
|
35
31
|
TestApp.linked_dirs.each do |dir|
|
36
|
-
|
32
|
+
run_remote_ssh_command(test_dir_exists(TestApp.shared_path.join(dir)))
|
37
33
|
end
|
38
34
|
end
|
39
35
|
|
40
36
|
Then(/^directories referenced in :linked_files are created in shared$/) do
|
41
37
|
dirs = TestApp.linked_files.map { |path| TestApp.shared_path.join(path).dirname }
|
42
38
|
dirs.each do |dir|
|
43
|
-
|
39
|
+
run_remote_ssh_command(test_dir_exists(dir))
|
44
40
|
end
|
45
41
|
end
|
46
42
|
|
47
43
|
Then(/^the repo is cloned$/) do
|
48
|
-
|
44
|
+
run_remote_ssh_command(test_dir_exists(TestApp.repo_path))
|
49
45
|
end
|
50
46
|
|
51
47
|
Then(/^the release is created$/) do
|
52
|
-
|
48
|
+
stdout, _stderr = run_remote_ssh_command("ls #{TestApp.releases_path}")
|
49
|
+
|
50
|
+
expect(stdout.strip).to match(/\A#{Time.now.utc.strftime("%Y%m%d")}\d{6}\Z/)
|
51
|
+
end
|
52
|
+
|
53
|
+
Then(/^the REVISION file is created in the release$/) do
|
54
|
+
stdout, _stderr = run_remote_ssh_command("cat #{@release_paths[0]}/REVISION")
|
55
|
+
|
56
|
+
expect(stdout.strip).to match(/\h{40}/)
|
57
|
+
end
|
58
|
+
|
59
|
+
Then(/^the REVISION_TIME file is created in the release$/) do
|
60
|
+
stdout, _stderr = run_remote_ssh_command("cat #{@release_paths[0]}/REVISION_TIME")
|
61
|
+
|
62
|
+
expect(stdout.strip).to match(/\d{10}/)
|
53
63
|
end
|
54
64
|
|
55
65
|
Then(/^file symlinks are created in the new release$/) do
|
56
66
|
TestApp.linked_files.each do |file|
|
57
|
-
|
67
|
+
run_remote_ssh_command(test_symlink_exists(TestApp.current_path.join(file)))
|
58
68
|
end
|
59
69
|
end
|
60
70
|
|
61
71
|
Then(/^directory symlinks are created in the new release$/) do
|
62
72
|
pending
|
63
73
|
TestApp.linked_dirs.each do |dir|
|
64
|
-
|
74
|
+
run_remote_ssh_command(test_symlink_exists(TestApp.release_path.join(dir)))
|
65
75
|
end
|
66
76
|
end
|
67
77
|
|
68
78
|
Then(/^the current directory will be a symlink to the release$/) do
|
69
|
-
|
79
|
+
run_remote_ssh_command(exists?("e", TestApp.current_path))
|
70
80
|
end
|
71
81
|
|
72
82
|
Then(/^the deploy\.rb file is created$/) do
|
@@ -95,7 +105,7 @@ end
|
|
95
105
|
|
96
106
|
Then(/^it creates the file with the remote_task prerequisite$/) do
|
97
107
|
TestApp.linked_files.each do |file|
|
98
|
-
|
108
|
+
run_remote_ssh_command(test_file_exists(TestApp.shared_path.join(file)))
|
99
109
|
end
|
100
110
|
end
|
101
111
|
|
@@ -113,18 +123,18 @@ end
|
|
113
123
|
|
114
124
|
Then(/^the failure task will run$/) do
|
115
125
|
failed = TestApp.shared_path.join("failed")
|
116
|
-
|
126
|
+
run_remote_ssh_command(test_file_exists(failed))
|
117
127
|
end
|
118
128
|
|
119
129
|
Then(/^the failure task will not run$/) do
|
120
130
|
failed = TestApp.shared_path.join("failed")
|
121
|
-
expect {
|
122
|
-
.to raise_error(
|
131
|
+
expect { run_remote_ssh_command(test_file_exists(failed)) }
|
132
|
+
.to raise_error(RemoteSSHHelpers::RemoteSSHCommandError)
|
123
133
|
end
|
124
134
|
|
125
135
|
When(/^an error is raised$/) do
|
126
136
|
error = TestApp.shared_path.join("fail")
|
127
|
-
|
137
|
+
run_remote_ssh_command(test_file_exists(error))
|
128
138
|
end
|
129
139
|
|
130
140
|
Then(/contains "([^"]*)" in the output/) do |expected|
|
@@ -142,11 +152,11 @@ end
|
|
142
152
|
Then(/the current symlink points to the previous release/) do
|
143
153
|
previous_release_path = @release_paths[-2]
|
144
154
|
|
145
|
-
|
155
|
+
run_remote_ssh_command(symlinked?(TestApp.current_path, previous_release_path))
|
146
156
|
end
|
147
157
|
|
148
158
|
Then(/^the current symlink points to that specific release$/) do
|
149
159
|
specific_release_path = TestApp.releases_path.join(@rollback_release)
|
150
160
|
|
151
|
-
|
161
|
+
run_remote_ssh_command(symlinked?(TestApp.current_path, specific_release_path))
|
152
162
|
end
|
@@ -7,11 +7,8 @@ Given(/^a test app without any configuration$/) do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
Given(/^servers with the roles app and web$/) do
|
10
|
-
|
11
|
-
|
12
|
-
rescue
|
13
|
-
nil
|
14
|
-
end
|
10
|
+
start_ssh_server
|
11
|
+
wait_for_ssh_server
|
15
12
|
end
|
16
13
|
|
17
14
|
Given(/^a linked file "(.*?)"$/) do |file|
|
@@ -21,8 +18,8 @@ end
|
|
21
18
|
|
22
19
|
Given(/^file "(.*?)" exists in shared path$/) do |file|
|
23
20
|
file_shared_path = TestApp.shared_path.join(file)
|
24
|
-
|
25
|
-
|
21
|
+
run_remote_ssh_command("mkdir -p #{file_shared_path.dirname}")
|
22
|
+
run_remote_ssh_command("touch #{file_shared_path}")
|
26
23
|
end
|
27
24
|
|
28
25
|
Given(/^all linked files exists in shared path$/) do
|
@@ -33,8 +30,8 @@ end
|
|
33
30
|
|
34
31
|
Given(/^file "(.*?)" does not exist in shared path$/) do |file|
|
35
32
|
file_shared_path = TestApp.shared_path.join(file)
|
36
|
-
|
37
|
-
|
33
|
+
run_remote_ssh_command("mkdir -p #{TestApp.shared_path}")
|
34
|
+
run_remote_ssh_command("touch #{file_shared_path} && rm #{file_shared_path}")
|
38
35
|
end
|
39
36
|
|
40
37
|
Given(/^a custom task to generate a file$/) do
|
@@ -67,12 +64,12 @@ Given(/^a stage file named (.+)$/) do |filename|
|
|
67
64
|
TestApp.write_local_stage_file(filename)
|
68
65
|
end
|
69
66
|
|
70
|
-
Given(/^I make (\d+) deployments
|
67
|
+
Given(/^I make (\d+) deployments?$/) do |count|
|
71
68
|
step "all linked files exists in shared path"
|
72
69
|
|
73
70
|
@release_paths = (1..count.to_i).map do
|
74
71
|
TestApp.cap("deploy")
|
75
|
-
stdout, _stderr =
|
72
|
+
stdout, _stderr = run_remote_ssh_command("readlink #{TestApp.current_path}")
|
76
73
|
|
77
74
|
stdout.strip
|
78
75
|
end
|
@@ -85,10 +82,10 @@ Given(/^(\d+) valid existing releases$/) do |num|
|
|
85
82
|
offset = -(a_day * i)
|
86
83
|
TestApp.release_path(TestApp.timestamp(offset))
|
87
84
|
end
|
88
|
-
|
85
|
+
run_remote_ssh_command("mkdir -p #{dirs.join(' ')}")
|
89
86
|
end
|
90
87
|
end
|
91
88
|
|
92
89
|
Given(/^an invalid release named "(.+)"$/) do |filename|
|
93
|
-
|
90
|
+
run_remote_ssh_command("mkdir -p #{TestApp.release_path(filename)}")
|
94
91
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Ensure Docker container is completely stopped when Ruby exits.
|
2
|
+
at_exit do
|
3
|
+
DockerGateway.new.stop
|
4
|
+
end
|
5
|
+
|
6
|
+
# Manages the Docker-based SSH server that is declared in docker-compose.yml.
|
7
|
+
class DockerGateway
|
8
|
+
def initialize(log_proc=$stderr.method(:puts))
|
9
|
+
@log_proc = log_proc
|
10
|
+
end
|
11
|
+
|
12
|
+
def start
|
13
|
+
run_compose_command("up -d")
|
14
|
+
end
|
15
|
+
|
16
|
+
def stop
|
17
|
+
run_compose_command("down")
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_shell_command(command)
|
21
|
+
run_compose_command("exec ssh_server /bin/bash -c #{command.shellescape}")
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def run_compose_command(command)
|
27
|
+
log "[docker compose] #{command}"
|
28
|
+
stdout, stderr, status = Open3.popen3("docker compose #{command}") do |stdin, stdout, stderr, wait_threads|
|
29
|
+
stdin << ""
|
30
|
+
stdin.close
|
31
|
+
out = Thread.new { read_lines(stdout, &$stdout.method(:puts)) }
|
32
|
+
err = Thread.new { stderr.read }
|
33
|
+
[out.value, err.value.to_s, wait_threads.value]
|
34
|
+
end
|
35
|
+
|
36
|
+
(stdout + stderr).each_line { |line| log "[docker compose] #{line}" }
|
37
|
+
|
38
|
+
[stdout, stderr, status]
|
39
|
+
end
|
40
|
+
|
41
|
+
def read_lines(io)
|
42
|
+
buffer = + ""
|
43
|
+
while (line = io.gets)
|
44
|
+
buffer << line
|
45
|
+
yield line
|
46
|
+
end
|
47
|
+
buffer
|
48
|
+
end
|
49
|
+
|
50
|
+
def log(message)
|
51
|
+
@log_proc.call(message)
|
52
|
+
end
|
53
|
+
end
|
data/features/support/env.rb
CHANGED
@@ -1,11 +1 @@
|
|
1
|
-
PROJECT_ROOT = File.expand_path("../../../", __FILE__)
|
2
|
-
VAGRANT_ROOT = File.join(PROJECT_ROOT, "spec/support")
|
3
|
-
VAGRANT_BIN = ENV["VAGRANT_BIN"] || "vagrant"
|
4
|
-
|
5
|
-
at_exit do
|
6
|
-
if ENV["KEEP_RUNNING"]
|
7
|
-
VagrantHelpers.run_vagrant_command("rm -rf /home/vagrant/var")
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
1
|
require_relative "../../spec/support/test_app"
|
@@ -12,7 +12,7 @@ module RemoteCommandHelpers
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def exists?(type, path)
|
15
|
-
%Q{[ -#{type} "#{path}" ]}
|
15
|
+
%Q{[[ -#{type} "#{path}" ]]}
|
16
16
|
end
|
17
17
|
|
18
18
|
def symlinked?(symlink_path, target_path)
|
@@ -20,9 +20,9 @@ module RemoteCommandHelpers
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def safely_remove_file(_path)
|
23
|
-
|
23
|
+
run_remote_ssh_command("rm #{test_file}")
|
24
24
|
rescue
|
25
|
-
|
25
|
+
RemoteSSHHelpers::RemoteSSHCommandError
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "open3"
|
2
|
+
require "socket"
|
3
|
+
require_relative "docker_gateway"
|
4
|
+
|
5
|
+
module RemoteSSHHelpers
|
6
|
+
extend self
|
7
|
+
|
8
|
+
class RemoteSSHCommandError < RuntimeError; end
|
9
|
+
|
10
|
+
def start_ssh_server
|
11
|
+
docker_gateway.start
|
12
|
+
end
|
13
|
+
|
14
|
+
def wait_for_ssh_server(retries=3)
|
15
|
+
Socket.tcp("localhost", 2022, connect_timeout: 1).close
|
16
|
+
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT
|
17
|
+
retries -= 1
|
18
|
+
sleep(2) && retry if retries.positive?
|
19
|
+
raise
|
20
|
+
end
|
21
|
+
|
22
|
+
def run_remote_ssh_command(command)
|
23
|
+
stdout, stderr, status = docker_gateway.run_shell_command(command)
|
24
|
+
return [stdout, stderr] if status.success?
|
25
|
+
raise RemoteSSHCommandError, status
|
26
|
+
end
|
27
|
+
|
28
|
+
def docker_gateway
|
29
|
+
@docker_gateway ||= DockerGateway.new(method(:log))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
World(RemoteSSHHelpers)
|
data/lib/capistrano/scm/git.rb
CHANGED
@@ -26,6 +26,7 @@ class Capistrano::SCM::Git < Capistrano::SCM::Plugin
|
|
26
26
|
after "deploy:new_release_path", "git:create_release"
|
27
27
|
before "deploy:check", "git:check"
|
28
28
|
before "deploy:set_current_revision", "git:set_current_revision"
|
29
|
+
before "deploy:set_current_revision_time", "git:set_current_revision_time"
|
29
30
|
end
|
30
31
|
|
31
32
|
def define_tasks
|
@@ -78,6 +79,10 @@ class Capistrano::SCM::Git < Capistrano::SCM::Plugin
|
|
78
79
|
backend.capture(:git, "rev-list --max-count=1 #{fetch(:branch)}")
|
79
80
|
end
|
80
81
|
|
82
|
+
def fetch_revision_time
|
83
|
+
backend.capture(:git, "log -1 --pretty=format:\"%ct\" #{fetch(:branch)}")
|
84
|
+
end
|
85
|
+
|
81
86
|
def git(*args)
|
82
87
|
args.unshift :git
|
83
88
|
backend.execute(*args)
|
@@ -70,4 +70,15 @@ namespace :git do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
74
|
+
desc "Determine the unix timestamp that the revision that will be deployed was created"
|
75
|
+
task :set_current_revision_time do
|
76
|
+
on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
|
77
|
+
within repo_path do
|
78
|
+
with fetch(:git_environmental_variables) do
|
79
|
+
set :current_revision_time, git_plugin.fetch_revision_time
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
73
84
|
end
|
@@ -3,6 +3,7 @@ namespace :deploy do
|
|
3
3
|
invoke "deploy:print_config_variables" if fetch(:print_config_variables, false)
|
4
4
|
invoke "deploy:check"
|
5
5
|
invoke "deploy:set_previous_revision"
|
6
|
+
invoke "deploy:set_previous_revision_time"
|
6
7
|
end
|
7
8
|
|
8
9
|
task :print_config_variables do
|
@@ -27,6 +28,7 @@ namespace :deploy do
|
|
27
28
|
|
28
29
|
task updating: :new_release_path do
|
29
30
|
invoke "deploy:set_current_revision"
|
31
|
+
invoke "deploy:set_current_revision_time"
|
30
32
|
invoke "deploy:symlink:shared"
|
31
33
|
end
|
32
34
|
|
@@ -236,7 +238,7 @@ namespace :deploy do
|
|
236
238
|
end
|
237
239
|
|
238
240
|
desc "Place a REVISION file with the current revision SHA in the current release path"
|
239
|
-
task :set_current_revision
|
241
|
+
task :set_current_revision do
|
240
242
|
on release_roles(:all) do
|
241
243
|
within release_path do
|
242
244
|
execute :echo, "\"#{fetch(:current_revision)}\" > REVISION"
|
@@ -253,6 +255,26 @@ namespace :deploy do
|
|
253
255
|
end
|
254
256
|
end
|
255
257
|
|
258
|
+
desc "Place a REVISION_TIME file with the current revision commit time in the current release path"
|
259
|
+
task :set_current_revision_time do
|
260
|
+
on release_roles(:all) do
|
261
|
+
within release_path do
|
262
|
+
if fetch(:current_revision_time)
|
263
|
+
execute :echo, "\"#{fetch(:current_revision_time)}\" > REVISION_TIME"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
task :set_previous_revision_time do
|
270
|
+
on release_roles(:all) do
|
271
|
+
target = release_path.join("REVISION_TIME")
|
272
|
+
if test "[ -f #{target} ]"
|
273
|
+
set(:previous_revision_time, capture(:cat, target, "2>/dev/null"))
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
256
278
|
task :restart
|
257
279
|
task :failed
|
258
280
|
end
|
data/lib/capistrano/version.rb
CHANGED
@@ -592,8 +592,8 @@ describe Capistrano::DSL do
|
|
592
592
|
|
593
593
|
it "yields the properties for a single role" do
|
594
594
|
recipient = mock("recipient")
|
595
|
-
recipient.expects(:doit).with("example1.com", :redis, port: 6379, type: :slave)
|
596
|
-
recipient.expects(:doit).with("example2.com", :redis, port: 6379, type: :master)
|
595
|
+
recipient.expects(:doit).with("example1.com", :redis, { port: 6379, type: :slave })
|
596
|
+
recipient.expects(:doit).with("example2.com", :redis, { port: 6379, type: :master })
|
597
597
|
dsl.role_properties(:redis) do |host, role, props|
|
598
598
|
recipient.doit(host, role, props)
|
599
599
|
end
|
@@ -601,8 +601,8 @@ describe Capistrano::DSL do
|
|
601
601
|
|
602
602
|
it "yields the properties for multiple roles" do
|
603
603
|
recipient = mock("recipient")
|
604
|
-
recipient.expects(:doit).with("example1.com", :redis, port: 6379, type: :slave)
|
605
|
-
recipient.expects(:doit).with("example2.com", :redis, port: 6379, type: :master)
|
604
|
+
recipient.expects(:doit).with("example1.com", :redis, { port: 6379, type: :slave })
|
605
|
+
recipient.expects(:doit).with("example2.com", :redis, { port: 6379, type: :master })
|
606
606
|
recipient.expects(:doit).with("example3.com", :app, nil)
|
607
607
|
dsl.role_properties(:redis, :app) do |host, role, props|
|
608
608
|
recipient.doit(host, role, props)
|
@@ -611,10 +611,10 @@ describe Capistrano::DSL do
|
|
611
611
|
|
612
612
|
it "yields the merged properties for multiple roles" do
|
613
613
|
recipient = mock("recipient")
|
614
|
-
recipient.expects(:doit).with("example1.com", :redis, port: 6379, type: :slave)
|
615
|
-
recipient.expects(:doit).with("example2.com", :redis, port: 6379, type: :master)
|
616
|
-
recipient.expects(:doit).with("example1.com", :web, port: 80)
|
617
|
-
recipient.expects(:doit).with("example2.com", :web, port: 81)
|
614
|
+
recipient.expects(:doit).with("example1.com", :redis, { port: 6379, type: :slave })
|
615
|
+
recipient.expects(:doit).with("example2.com", :redis, { port: 6379, type: :master })
|
616
|
+
recipient.expects(:doit).with("example1.com", :web, { port: 80 })
|
617
|
+
recipient.expects(:doit).with("example2.com", :web, { port: 81 })
|
618
618
|
dsl.role_properties(:redis, :web) do |host, role, props|
|
619
619
|
recipient.doit(host, role, props)
|
620
620
|
end
|
@@ -622,8 +622,8 @@ describe Capistrano::DSL do
|
|
622
622
|
|
623
623
|
it "honours a property filter before yielding" do
|
624
624
|
recipient = mock("recipient")
|
625
|
-
recipient.expects(:doit).with("example1.com", :redis, port: 6379, type: :slave)
|
626
|
-
recipient.expects(:doit).with("example1.com", :web, port: 80)
|
625
|
+
recipient.expects(:doit).with("example1.com", :redis, { port: 6379, type: :slave })
|
626
|
+
recipient.expects(:doit).with("example1.com", :web, { port: 80 })
|
627
627
|
dsl.role_properties(:redis, :web, select: :active) do |host, role, props|
|
628
628
|
recipient.doit(host, role, props)
|
629
629
|
end
|
@@ -12,6 +12,7 @@ module Capistrano
|
|
12
12
|
Rake::Task.define_task("deploy:check")
|
13
13
|
Rake::Task.define_task("deploy:new_release_path")
|
14
14
|
Rake::Task.define_task("deploy:set_current_revision")
|
15
|
+
Rake::Task.define_task("deploy:set_current_revision_time")
|
15
16
|
set :scm, SCMResolver::DEFAULT_GIT
|
16
17
|
end
|
17
18
|
|
@@ -19,6 +19,7 @@ module Capistrano
|
|
19
19
|
Rake::Task.define_task("deploy:new_release_path")
|
20
20
|
Rake::Task.define_task("deploy:check")
|
21
21
|
Rake::Task.define_task("deploy:set_current_revision")
|
22
|
+
Rake::Task.define_task("deploy:set_current_revision_time")
|
22
23
|
end
|
23
24
|
|
24
25
|
# Clean up any tasks or variables that the plugin defined.
|
@@ -170,6 +171,15 @@ module Capistrano
|
|
170
171
|
end
|
171
172
|
end
|
172
173
|
|
174
|
+
describe "#fetch_revision_time" do
|
175
|
+
it "should capture git log" do
|
176
|
+
env.set(:branch, "branch")
|
177
|
+
backend.expects(:capture).with(:git, "log -1 --pretty=format:\"%ct\" branch").returns("1715828406")
|
178
|
+
revision_time = subject.fetch_revision_time
|
179
|
+
expect(revision_time).to eq("1715828406")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
173
183
|
describe "#verify_commit" do
|
174
184
|
it "should run git verify-commit" do
|
175
185
|
env.set(:branch, "branch")
|
data/spec/support/test_app.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "English"
|
2
2
|
require "fileutils"
|
3
3
|
require "pathname"
|
4
|
+
require "open3"
|
4
5
|
|
5
6
|
module TestApp
|
6
7
|
extend self
|
@@ -14,8 +15,8 @@ module TestApp
|
|
14
15
|
set :deploy_to, '#{deploy_to}'
|
15
16
|
set :repo_url, 'https://github.com/capistrano/capistrano.git'
|
16
17
|
set :branch, 'master'
|
17
|
-
set :ssh_options, { keys:
|
18
|
-
server '
|
18
|
+
set :ssh_options, { keys: '#{File.expand_path('../../.docker/ssh_key_rsa', __dir__)}', auth_methods: ['publickey'] }
|
19
|
+
server 'deployer@localhost:2022', roles: %w{web app}
|
19
20
|
set :linked_files, #{linked_files}
|
20
21
|
set :linked_dirs, #{linked_dirs}
|
21
22
|
set :format_options, log_file: nil
|
@@ -39,10 +40,13 @@ module TestApp
|
|
39
40
|
FileUtils.rm_rf(test_app_path)
|
40
41
|
FileUtils.mkdir(test_app_path)
|
41
42
|
|
42
|
-
File.
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
File.write(gemfile, <<-GEMFILE.gsub(/^\s+/, ""))
|
44
|
+
source "https://rubygems.org"
|
45
|
+
|
46
|
+
gem "capistrano", path: #{path_to_cap.to_s.inspect}
|
47
|
+
gem "ed25519", ">= 1.2", "< 2.0"
|
48
|
+
gem "bcrypt_pbkdf", ">= 1.0", "< 2.0"
|
49
|
+
GEMFILE
|
46
50
|
|
47
51
|
Dir.chdir(test_app_path) do
|
48
52
|
run "bundle"
|
@@ -96,13 +100,12 @@ module TestApp
|
|
96
100
|
end
|
97
101
|
|
98
102
|
def run(command, subdirectory=nil)
|
99
|
-
output = nil
|
100
103
|
command = "bundle exec #{command}" unless command =~ /^bundle\b/
|
101
104
|
dir = subdirectory ? test_app_path.join(subdirectory) : test_app_path
|
102
|
-
Dir.chdir(dir) do
|
103
|
-
|
105
|
+
output, status = Dir.chdir(dir) do
|
106
|
+
with_clean_bundler_env { Open3.capture2e(command) }
|
104
107
|
end
|
105
|
-
[
|
108
|
+
[status.success?, output]
|
106
109
|
end
|
107
110
|
|
108
111
|
def stage
|
@@ -118,7 +121,7 @@ module TestApp
|
|
118
121
|
end
|
119
122
|
|
120
123
|
def deploy_to
|
121
|
-
Pathname.new("/home/
|
124
|
+
Pathname.new("/home/deployer/var/www/deploy")
|
122
125
|
end
|
123
126
|
|
124
127
|
def shared_path
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Clements
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: airbrussh
|
@@ -78,6 +78,10 @@ executables:
|
|
78
78
|
extensions: []
|
79
79
|
extra_rdoc_files: []
|
80
80
|
files:
|
81
|
+
- ".docker/Dockerfile"
|
82
|
+
- ".docker/ssh_key_rsa"
|
83
|
+
- ".docker/ssh_key_rsa.pub"
|
84
|
+
- ".docker/ubuntu_setup.sh"
|
81
85
|
- ".github/issue_template.md"
|
82
86
|
- ".github/pull_request_template.md"
|
83
87
|
- ".github/release-drafter.yml"
|
@@ -88,7 +92,6 @@ files:
|
|
88
92
|
- CHANGELOG.md
|
89
93
|
- CONTRIBUTING.md
|
90
94
|
- DEVELOPMENT.md
|
91
|
-
- Dangerfile
|
92
95
|
- Gemfile
|
93
96
|
- LICENSE.txt
|
94
97
|
- README.md
|
@@ -98,6 +101,7 @@ files:
|
|
98
101
|
- bin/cap
|
99
102
|
- bin/capify
|
100
103
|
- capistrano.gemspec
|
104
|
+
- docker-compose.yml
|
101
105
|
- features/configuration.feature
|
102
106
|
- features/deploy.feature
|
103
107
|
- features/deploy_failure.feature
|
@@ -109,9 +113,10 @@ files:
|
|
109
113
|
- features/step_definitions/cap_commands.rb
|
110
114
|
- features/step_definitions/setup.rb
|
111
115
|
- features/subdirectory.feature
|
116
|
+
- features/support/docker_gateway.rb
|
112
117
|
- features/support/env.rb
|
113
118
|
- features/support/remote_command_helpers.rb
|
114
|
-
- features/support/
|
119
|
+
- features/support/remote_ssh_helpers.rb
|
115
120
|
- lib/Capfile
|
116
121
|
- lib/capistrano.rb
|
117
122
|
- lib/capistrano/all.rb
|
@@ -202,8 +207,6 @@ files:
|
|
202
207
|
- spec/lib/capistrano/version_validator_spec.rb
|
203
208
|
- spec/lib/capistrano_spec.rb
|
204
209
|
- spec/spec_helper.rb
|
205
|
-
- spec/support/.gitignore
|
206
|
-
- spec/support/Vagrantfile
|
207
210
|
- spec/support/matchers.rb
|
208
211
|
- spec/support/tasks/database.rake
|
209
212
|
- spec/support/tasks/fail.rake
|
@@ -235,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
238
|
- !ruby/object:Gem::Version
|
236
239
|
version: '0'
|
237
240
|
requirements: []
|
238
|
-
rubygems_version: 3.5.
|
241
|
+
rubygems_version: 3.5.8
|
239
242
|
signing_key:
|
240
243
|
specification_version: 4
|
241
244
|
summary: Capistrano - Welcome to easy deployment with Ruby over SSH
|
@@ -251,9 +254,10 @@ test_files:
|
|
251
254
|
- features/step_definitions/cap_commands.rb
|
252
255
|
- features/step_definitions/setup.rb
|
253
256
|
- features/subdirectory.feature
|
257
|
+
- features/support/docker_gateway.rb
|
254
258
|
- features/support/env.rb
|
255
259
|
- features/support/remote_command_helpers.rb
|
256
|
-
- features/support/
|
260
|
+
- features/support/remote_ssh_helpers.rb
|
257
261
|
- spec/integration/dsl_spec.rb
|
258
262
|
- spec/integration_spec_helper.rb
|
259
263
|
- spec/lib/capistrano/application_spec.rb
|
@@ -286,8 +290,6 @@ test_files:
|
|
286
290
|
- spec/lib/capistrano/version_validator_spec.rb
|
287
291
|
- spec/lib/capistrano_spec.rb
|
288
292
|
- spec/spec_helper.rb
|
289
|
-
- spec/support/.gitignore
|
290
|
-
- spec/support/Vagrantfile
|
291
293
|
- spec/support/matchers.rb
|
292
294
|
- spec/support/tasks/database.rake
|
293
295
|
- spec/support/tasks/fail.rake
|
data/Dangerfile
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
danger.import_dangerfile(github: "capistrano/danger", branch: "no-changelog")
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require "open3"
|
2
|
-
|
3
|
-
module VagrantHelpers
|
4
|
-
extend self
|
5
|
-
|
6
|
-
class VagrantSSHCommandError < RuntimeError; end
|
7
|
-
|
8
|
-
at_exit do
|
9
|
-
if ENV["KEEP_RUNNING"]
|
10
|
-
puts "Vagrant vm will be left up because KEEP_RUNNING is set."
|
11
|
-
puts "Rerun without KEEP_RUNNING set to cleanup the vm."
|
12
|
-
else
|
13
|
-
vagrant_cli_command("destroy -f")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def vagrant_cli_command(command)
|
18
|
-
puts "[vagrant] #{command}"
|
19
|
-
stdout, stderr, status = Dir.chdir(VAGRANT_ROOT) do
|
20
|
-
Open3.capture3("#{VAGRANT_BIN} #{command}")
|
21
|
-
end
|
22
|
-
|
23
|
-
(stdout + stderr).each_line { |line| puts "[vagrant] #{line}" }
|
24
|
-
|
25
|
-
[stdout, stderr, status]
|
26
|
-
end
|
27
|
-
|
28
|
-
def run_vagrant_command(command)
|
29
|
-
stdout, stderr, status = vagrant_cli_command("ssh -c #{command.inspect}")
|
30
|
-
return [stdout, stderr] if status.success?
|
31
|
-
raise VagrantSSHCommandError, status
|
32
|
-
end
|
33
|
-
|
34
|
-
def puts(message)
|
35
|
-
# Attach log messages to the current cucumber feature (`log`),
|
36
|
-
# or simply puts to the console (`super`) if we are outside of cucumber.
|
37
|
-
respond_to?(:log) ? log(message) : super(message)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
World(VagrantHelpers)
|
data/spec/support/.gitignore
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
.vagrant
|
data/spec/support/Vagrantfile
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require "open-uri"
|
2
|
-
|
3
|
-
Vagrant.configure("2") do |config|
|
4
|
-
config.ssh.insert_key = false
|
5
|
-
|
6
|
-
[:app].each_with_index do |role, i|
|
7
|
-
config.vm.define(role, primary: true) do |primary|
|
8
|
-
primary.vm.define role
|
9
|
-
primary.vm.box = "hashicorp/bionic64"
|
10
|
-
primary.vm.network "forwarded_port", guest: 22, host: "222#{i}".to_i
|
11
|
-
primary.vm.provision :shell, inline: "sudo apt-get -y install git-core"
|
12
|
-
|
13
|
-
vagrantkey = URI.open("https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub", "r", &:read)
|
14
|
-
|
15
|
-
primary.vm.provision :shell,
|
16
|
-
inline: <<-INLINE
|
17
|
-
install -d -m 700 /root/.ssh
|
18
|
-
echo -e "#{vagrantkey}" > /root/.ssh/authorized_keys
|
19
|
-
chmod 0600 /root/.ssh/authorized_keys
|
20
|
-
INLINE
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|