vagrant-unbundled 2.2.18.0 → 2.2.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +6 -6
- data/contrib/zsh/generate_zsh_completion.rb +2 -2
- data/lib/vagrant/errors.rb +8 -0
- data/plugins/commands/upload/command.rb +1 -1
- data/plugins/guests/atomic/guest.rb +1 -1
- data/plugins/guests/coreos/cap/configure_networks.rb +65 -0
- data/plugins/guests/darwin/cap/mount_smb_shared_folder.rb +6 -3
- data/plugins/guests/suse/cap/halt.rb +5 -1
- data/plugins/guests/windows/cap/rsync.rb +5 -1
- data/plugins/hosts/darwin/cap/path.rb +4 -0
- data/plugins/hosts/darwin/cap/version.rb +23 -0
- data/plugins/hosts/darwin/plugin.rb +5 -0
- data/plugins/hosts/windows/cap/ssh.rb +1 -1
- data/plugins/providers/virtualbox/action/network.rb +39 -2
- data/plugins/provisioners/chef/cap/freebsd/chef_installed.rb +5 -3
- data/plugins/provisioners/chef/cap/linux/chef_installed.rb +5 -3
- data/plugins/provisioners/chef/cap/omnios/chef_installed.rb +7 -5
- data/plugins/provisioners/chef/cap/windows/chef_installed.rb +3 -2
- data/templates/locales/en.yml +25 -0
- data/vagrant.gemspec +1 -1
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/CONTRIBUTING.md +23 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/CONTRIBUTORS.md +140 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/LICENSE.md +20 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/README.md +492 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/data/cacert.pem +3232 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/excon.gemspec +45 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/connection.rb +599 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/constants.rb +172 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/error.rb +229 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/extensions/uri.rb +34 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/headers.rb +85 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/instrumentors/logging_instrumentor.rb +48 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/instrumentors/standard_instrumentor.rb +21 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/base.rb +31 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/capture_cookies.rb +32 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/decompress.rb +44 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/escape_path.rb +12 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/expects.rb +25 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/idempotent.rb +57 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/instrumentor.rb +49 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/mock.rb +61 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/redirect_follower.rb +87 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/middlewares/response_parser.rb +16 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/pretty_printer.rb +39 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/response.rb +234 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/socket.rb +297 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/ssl_socket.rb +194 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/plugin/server/exec.rb +26 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/plugin/server/puma.rb +23 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/plugin/server/unicorn.rb +40 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/plugin/server/webrick.rb +26 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/test/server.rb +106 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/unix_socket.rb +42 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/utils.rb +143 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon/version.rb +4 -0
- data/vendor/bundle/ruby/3.0.0/gems/excon-0.89.0/lib/excon.rb +255 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/MIT-LICENSE +20 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/README.md +122 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/base.rb +289 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/cache.rb +113 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/cache_file.rb +36 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/cascade.rb +56 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/chain.rb +130 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/fallbacks.rb +97 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/flatten.rb +118 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/gettext.rb +85 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/interpolation_compiler.rb +123 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/key_value.rb +206 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/memoize.rb +54 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/metadata.rb +71 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/pluralization.rb +55 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/simple.rb +108 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend/transliterator.rb +108 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/backend.rb +21 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/config.rb +165 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/core_ext/hash.rb +59 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/exceptions.rb +111 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/gettext/helpers.rb +75 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/gettext/po_parser.rb +329 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/gettext.rb +28 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/interpolate/ruby.rb +39 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/fallbacks.rb +99 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/tag/parents.rb +24 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/tag/rfc4646.rb +74 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/tag/simple.rb +39 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale/tag.rb +28 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/locale.rb +8 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/middleware.rb +17 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/basics.rb +60 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/defaults.rb +52 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/interpolation.rb +163 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/link.rb +66 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization/date.rb +117 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization/date_time.rb +103 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization/procs.rb +117 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization/time.rb +103 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/localization.rb +19 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/lookup.rb +81 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/pluralization.rb +35 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests/procs.rb +60 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/tests.rb +14 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n/version.rb +5 -0
- data/vendor/bundle/ruby/3.0.0/gems/i18n-1.8.11/lib/i18n.rb +415 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Code-of-Conduct.md +73 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Contributing.md +132 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/History.md +269 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Licence.md +25 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Manifest.txt +31 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/README.rdoc +194 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/Rakefile +270 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/type/columnar.rb +57 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/type.rb +634 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/_columnar.rb +137 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/cache.rb +58 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/columnar.rb +3 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/container.rb +96 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/deprecations.rb +36 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/full.rb +19 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/loader.rb +159 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/logger.rb +37 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types/registry.rb +90 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime/types.rb +233 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/lib/mime-types.rb +3 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/bad-fixtures/malformed +9 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/fixture/json.json +1 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/fixture/old-data +9 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/fixture/yaml.yaml +55 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/minitest_helper.rb +11 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_type.rb +621 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types.rb +169 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types_cache.rb +118 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types_class.rb +159 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types_lazy.rb +49 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-3.4.1/test/test_mime_types_loader.rb +32 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Code-of-Conduct.md +75 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Contributing.md +241 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/History.md +494 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Licence.md +24 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Manifest.txt +34 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/README.md +73 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/Rakefile +155 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/content_type_mime.db +878 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/ext_mime.db +1198 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime-types.json +1 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.content_type.column +2376 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.docs.column +2376 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.encoding.column +2376 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.flags.column +2376 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.friendly.column +2376 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.pext.column +2376 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.use_instead.column +2376 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/data/mime.xrefs.column +2376 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/lib/mime/types/data.rb +21 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/lib/mime-types-data.rb +3 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/application.yaml +17254 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/audio.yaml +1716 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/chemical.yaml +71 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/conference.yaml +9 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/drawing.yaml +15 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/font.yaml +65 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/image.yaml +1251 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/message.yaml +200 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/model.yaml +390 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/multipart.yaml +179 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/provisional-standard-types.yaml +129 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/text.yaml +1166 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/video.yaml +1121 -0
- data/vendor/bundle/ruby/3.0.0/gems/mime-types-data-3.2021.1115/types/world.yaml +8 -0
- data/vendor/bundle/ruby/3.0.0/specifications/excon-0.89.0.gemspec +58 -0
- data/vendor/bundle/ruby/3.0.0/specifications/i18n-1.8.11.gemspec +32 -0
- data/vendor/bundle/ruby/3.0.0/specifications/mime-types-3.4.1.gemspec +63 -0
- data/vendor/bundle/ruby/3.0.0/specifications/mime-types-data-3.2021.1115.gemspec +54 -0
- data/version.txt +1 -1
- metadata +157 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54a028024291e4538676f5c0b426facd4668d839afe46a6c62def66358317bc9
|
4
|
+
data.tar.gz: cedbca4e8f4d3003875506217a34bf1e3abb29e0726e6799f6e86a1bc2f77af7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65709b560351a9547f47391889803cfea3b5ac89df8be43cb4670be1c23d402d95f6aef3d9154d446012b1d8035eb7203e8b7c6e9131acbf0e4c7eb184834f51
|
7
|
+
data.tar.gz: 469141800334a479d4fef8e15518a2efdac426c4ed2afeef0add67b37026857b08d02fdaa710fb68c1368af3efc955849437116ac4d5bba2884e6b008039e87a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 2.2.19 (November 5, 2021)
|
2
|
+
|
3
|
+
IMPROVEMENTS:
|
4
|
+
|
5
|
+
- guest/suse: Add fallback shutdown for versions without systemd [GH-12489]
|
6
|
+
- provider/virtualbox: Validate VirtualBox hostonly network range [GH-12564]
|
7
|
+
|
8
|
+
BUG FIXES
|
9
|
+
|
10
|
+
- guest/atomic: Update detection to prevent matching on non-atomic guests [GH-12575]
|
11
|
+
- guest/coreos: Fix configure network capability [GH-12575]
|
12
|
+
- guest/windows: Fix directory creation with rsync [GH-11880]
|
13
|
+
- host/windows: Properly handle spaces in path to SSH key [GH-12398]
|
14
|
+
- provisioner/chef: Update install checks [GH-12555]
|
15
|
+
|
1
16
|
## 2.2.18 (July 27, 2021)
|
2
17
|
|
3
18
|
BUG FIXES:
|
data/Gemfile.lock
CHANGED
@@ -12,14 +12,14 @@ GIT
|
|
12
12
|
PATH
|
13
13
|
remote: .
|
14
14
|
specs:
|
15
|
-
vagrant-unbundled (2.2.
|
15
|
+
vagrant-unbundled (2.2.19.0)
|
16
16
|
bcrypt_pbkdf (~> 1.1)
|
17
17
|
childprocess (~> 4.1.0)
|
18
18
|
ed25519 (~> 1.2.4)
|
19
19
|
erubi
|
20
20
|
hashicorp-checkpoint (~> 0.1.5)
|
21
21
|
i18n (~> 1.8)
|
22
|
-
listen (~> 3.
|
22
|
+
listen (~> 3.6)
|
23
23
|
log4r (~> 1.1.9, < 1.1.11)
|
24
24
|
mime-types (~> 3.3)
|
25
25
|
net-scp (~> 3.0.0)
|
@@ -44,7 +44,7 @@ GEM
|
|
44
44
|
diff-lcs (1.4.4)
|
45
45
|
ed25519 (1.2.4)
|
46
46
|
erubi (1.10.0)
|
47
|
-
excon (0.
|
47
|
+
excon (0.89.0)
|
48
48
|
fake_ftp (0.1.1)
|
49
49
|
ffi (1.15.4)
|
50
50
|
gssapi (1.3.1)
|
@@ -53,7 +53,7 @@ GEM
|
|
53
53
|
builder (>= 2.1.2)
|
54
54
|
hashicorp-checkpoint (0.1.5)
|
55
55
|
httpclient (2.8.3)
|
56
|
-
i18n (1.8.
|
56
|
+
i18n (1.8.11)
|
57
57
|
concurrent-ruby (~> 1.0)
|
58
58
|
listen (3.7.0)
|
59
59
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
@@ -63,9 +63,9 @@ GEM
|
|
63
63
|
logging (2.3.0)
|
64
64
|
little-plugger (~> 1.1)
|
65
65
|
multi_json (~> 1.14)
|
66
|
-
mime-types (3.
|
66
|
+
mime-types (3.4.1)
|
67
67
|
mime-types-data (~> 3.2015)
|
68
|
-
mime-types-data (3.2021.
|
68
|
+
mime-types-data (3.2021.1115)
|
69
69
|
multi_json (1.15.0)
|
70
70
|
net-scp (3.0.0)
|
71
71
|
net-ssh (>= 2.6.5, < 7.0.0)
|
@@ -121,11 +121,11 @@ def get_top_level_commands(root_command, cmd_list)
|
|
121
121
|
return commands, flags_def, case_string
|
122
122
|
end
|
123
123
|
|
124
|
-
def format_script(root_command, subcommands,
|
124
|
+
def format_script(root_command, subcommands, function_name)
|
125
125
|
top_level_commands, top_level_args, state_case = get_top_level_commands(root_command, subcommands)
|
126
126
|
|
127
127
|
script = """
|
128
|
-
function #{
|
128
|
+
function #{function_name} () {
|
129
129
|
|
130
130
|
#{top_level_commands}
|
131
131
|
|
data/lib/vagrant/errors.rb
CHANGED
@@ -356,6 +356,10 @@ module Vagrant
|
|
356
356
|
error_key(:darwin_mount_failed)
|
357
357
|
end
|
358
358
|
|
359
|
+
class DarwinVersionFailed < VagrantError
|
360
|
+
error_key(:darwin_version_failed)
|
361
|
+
end
|
362
|
+
|
359
363
|
class DestroyRequiresForce < VagrantError
|
360
364
|
error_key(:destroy_requires_force)
|
361
365
|
end
|
@@ -1024,6 +1028,10 @@ module Vagrant
|
|
1024
1028
|
error_key(:virtualbox_version_empty)
|
1025
1029
|
end
|
1026
1030
|
|
1031
|
+
class VirtualBoxInvalidHostSubnet < VagrantError
|
1032
|
+
error_key(:virtualbox_invalid_host_subnet)
|
1033
|
+
end
|
1034
|
+
|
1027
1035
|
class VMBaseMacNotSpecified < VagrantError
|
1028
1036
|
error_key(:no_base_mac, "vagrant.actions.vm.match_mac")
|
1029
1037
|
end
|
@@ -52,7 +52,7 @@ module VagrantPlugins
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# NOTE: We do this to handle paths on Windows like: "..\space dir\"
|
55
|
-
# because the final
|
55
|
+
# because the final separator acts to escape the quote and ends up
|
56
56
|
# in the source value.
|
57
57
|
source = source.sub(/["']$/, "")
|
58
58
|
destination ||= File.basename(source)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "tempfile"
|
2
|
+
require "yaml"
|
2
3
|
|
3
4
|
require_relative "../../../../lib/vagrant/util/template_renderer"
|
4
5
|
|
@@ -8,9 +9,73 @@ module VagrantPlugins
|
|
8
9
|
class ConfigureNetworks
|
9
10
|
extend Vagrant::Util::GuestInspection::Linux
|
10
11
|
|
12
|
+
NETWORK_MANAGER_CONN_DIR = "/etc/NetworkManager/system-connections".freeze
|
11
13
|
DEFAULT_ENVIRONMENT_IP = "127.0.0.1".freeze
|
12
14
|
|
13
15
|
def self.configure_networks(machine, networks)
|
16
|
+
comm = machine.communicate
|
17
|
+
return configure_networks_cloud_init(machine, networks) if comm.test("command -v cloud-init")
|
18
|
+
|
19
|
+
interfaces = machine.guest.capability(:network_interfaces)
|
20
|
+
nm_dev = {}
|
21
|
+
comm.execute("nmcli -t c show") do |type, data|
|
22
|
+
if type == :stdout
|
23
|
+
_, id, _, dev = data.strip.split(":")
|
24
|
+
nm_dev[dev] = id
|
25
|
+
end
|
26
|
+
end
|
27
|
+
comm.sudo("rm #{File.join(NETWORK_MANAGER_CONN_DIR, 'vagrant-*.conf')}",
|
28
|
+
error_check: false)
|
29
|
+
|
30
|
+
networks.each_with_index do |network, i|
|
31
|
+
network[:device] = interfaces[network[:interface]]
|
32
|
+
addr = IPAddr.new(network[:ip])
|
33
|
+
mask = addr.mask(network[:netmask])
|
34
|
+
if !network[:mac_address]
|
35
|
+
comm.execute("cat /sys/class/net/#{network[:device]}/address") do |type, data|
|
36
|
+
if type == :stdout
|
37
|
+
network[:mac_address] = data
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
f = Tempfile.new("vagrant-coreos-network")
|
43
|
+
{
|
44
|
+
connection: {
|
45
|
+
type: "ethernet",
|
46
|
+
id: network[:device],
|
47
|
+
"interface-name": network[:device]
|
48
|
+
},
|
49
|
+
ethernet: {
|
50
|
+
"mac-address": network[:mac_address]
|
51
|
+
},
|
52
|
+
ipv4: {
|
53
|
+
method: "manual",
|
54
|
+
addresses: "#{network[:ip]}/#{mask.prefix}",
|
55
|
+
gateway: network.fetch(:gateway, mask.to_range.first.succ),
|
56
|
+
},
|
57
|
+
}.each_pair do |section, content|
|
58
|
+
f.puts "[#{section}]"
|
59
|
+
content.each_pair do |key, value|
|
60
|
+
f.puts "#{key}=#{value}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
f.close
|
64
|
+
comm.sudo("nmcli d disconnect '#{network[:device]}'", error_check: false)
|
65
|
+
comm.sudo("nmcli c delete '#{nm_dev[network[:device]]}'", error_check: false)
|
66
|
+
dst = File.join("/var/tmp", "vagrant-#{network[:device]}.conf")
|
67
|
+
final = File.join(NETWORK_MANAGER_CONN_DIR, "vagrant-#{network[:device]}.conf")
|
68
|
+
comm.upload(f.path, dst)
|
69
|
+
comm.sudo("chown root:root '#{dst}'")
|
70
|
+
comm.sudo("chmod 0600 '#{dst}'")
|
71
|
+
comm.sudo("mv '#{dst}' '#{final}'")
|
72
|
+
comm.sudo("nmcli c load '#{final}'")
|
73
|
+
comm.sudo("nmcli d connect '#{network[:device]}'")
|
74
|
+
f.delete
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.configure_networks_cloud_init(machine, networks)
|
14
79
|
cloud_config = {}
|
15
80
|
# Locate configured IP addresses to drop in /etc/environment
|
16
81
|
# for export. If no addresses found, fall back to default
|
@@ -29,9 +29,12 @@ module VagrantPlugins
|
|
29
29
|
"//#{options[:smb_username]}:#{smb_password}@#{options[:smb_host]}/#{name} " +
|
30
30
|
"#{expanded_guest_path}"
|
31
31
|
retryable(on: Vagrant::Errors::DarwinMountFailed, tries: 10, sleep: 2) do
|
32
|
-
machine.communicate.execute(
|
33
|
-
|
34
|
-
|
32
|
+
result = machine.communicate.execute(mount_command)
|
33
|
+
if result.exit_code != 0
|
34
|
+
raise Vagrant::Errors::DarwinMountFailed,
|
35
|
+
command: mount_command,
|
36
|
+
output: result.stderr
|
37
|
+
end
|
35
38
|
end
|
36
39
|
end
|
37
40
|
end
|
@@ -4,7 +4,11 @@ module VagrantPlugins
|
|
4
4
|
class Halt
|
5
5
|
def self.halt(machine)
|
6
6
|
begin
|
7
|
-
machine.communicate.
|
7
|
+
if machine.communicate.test("test -e /usr/bin/systemctl")
|
8
|
+
machine.communicate.sudo("/usr/bin/systemctl poweroff &")
|
9
|
+
else
|
10
|
+
machine.communicate.sudo("/sbin/shutdown -h now &")
|
11
|
+
end
|
8
12
|
rescue IOError, Vagrant::Errors::SSHDisconnected
|
9
13
|
# Do nothing, because it probably means the machine shut down
|
10
14
|
# and SSH connection was lost.
|
@@ -13,7 +13,11 @@ module VagrantPlugins
|
|
13
13
|
machine.communicate.tap do |comm|
|
14
14
|
# rsync does not construct any gaps in the path to the target directory
|
15
15
|
# make sure that all subdirectories are created
|
16
|
-
|
16
|
+
# NB: Per #11878, the `mkdir` command on Windows is different than used on Unix.
|
17
|
+
# This formulation matches the form used in the WinRM communicator plugin.
|
18
|
+
# This will ignore any -p switches, which are redundant in PowerShell,
|
19
|
+
# and ambiguous in PowerShell 4+
|
20
|
+
comm.execute("mkdir \"#{opts[:guestpath]}\" -force")
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
@@ -6,6 +6,7 @@ module VagrantPlugins
|
|
6
6
|
|
7
7
|
FIRMLINK_DEFS = "/usr/share/firmlinks".freeze
|
8
8
|
FIRMLINK_DATA_PATH = "/System/Volumes/Data".freeze
|
9
|
+
CATALINA_CONSTRAINT = Gem::Requirement.new("~> 10.15")
|
9
10
|
|
10
11
|
# Resolve the given host path to the actual
|
11
12
|
# usable system path by detecting firmlinks
|
@@ -15,6 +16,9 @@ module VagrantPlugins
|
|
15
16
|
# @return [String] resolved path
|
16
17
|
def self.resolve_host_path(env, path)
|
17
18
|
path = File.expand_path(path)
|
19
|
+
# Only expand firmlink paths on Catalina
|
20
|
+
return path if !CATALINA_CONSTRAINT.satisfied_by?(Cap::Version.version(env))
|
21
|
+
|
18
22
|
firmlink = firmlink_map.detect do |mount_path, data_path|
|
19
23
|
path.start_with?(mount_path)
|
20
24
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module HostDarwin
|
3
|
+
module Cap
|
4
|
+
class Version
|
5
|
+
def self.version(env)
|
6
|
+
r = Vagrant::Util::Subprocess.execute("sw_vers", "-productVersion")
|
7
|
+
if r.exit_code != 0
|
8
|
+
raise Vagrant::Errors::DarwinVersionFailed,
|
9
|
+
version: r.stdout,
|
10
|
+
error: r.stderr
|
11
|
+
end
|
12
|
+
begin
|
13
|
+
Gem::Version.new(r.stdout)
|
14
|
+
rescue => err
|
15
|
+
raise Vagrant::Errors::DarwinVersionFailed,
|
16
|
+
version: r.stdout,
|
17
|
+
error: err.message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -10,7 +10,7 @@ module VagrantPlugins
|
|
10
10
|
def self.set_ssh_key_permissions(env, key_path)
|
11
11
|
script_path = Host.scripts_path.join("set_ssh_key_permissions.ps1")
|
12
12
|
result = Vagrant::Util::PowerShell.execute(
|
13
|
-
script_path.to_s, "-KeyPath", key_path.to_s,
|
13
|
+
script_path.to_s, "-KeyPath", key_path.to_s.gsub(' ', '` '),
|
14
14
|
module_path: Host.modules_path.to_s
|
15
15
|
)
|
16
16
|
if result.exit_code != 0
|
@@ -16,6 +16,14 @@ module VagrantPlugins
|
|
16
16
|
#
|
17
17
|
# This handles all the `config.vm.network` configurations.
|
18
18
|
class Network
|
19
|
+
|
20
|
+
# Location of the VirtualBox networks configuration file
|
21
|
+
VBOX_NET_CONF = "/etc/vbox/networks.conf".freeze
|
22
|
+
# Version of VirtualBox that introduced hostonly network range restrictions
|
23
|
+
HOSTONLY_VALIDATE_VERSION = Gem::Version.new("6.1.28")
|
24
|
+
# Default valid range for hostonly networks
|
25
|
+
HOSTONLY_DEFAULT_RANGE = [IPAddr.new("192.168.56.0/21").freeze].freeze
|
26
|
+
|
19
27
|
include Vagrant::Util::NetworkIP
|
20
28
|
include Vagrant::Util::ScopedHashOverride
|
21
29
|
|
@@ -255,7 +263,7 @@ module VagrantPlugins
|
|
255
263
|
|
256
264
|
# Make sure the type is a symbol
|
257
265
|
options[:type] = options[:type].to_sym
|
258
|
-
|
266
|
+
|
259
267
|
if options[:type] == :dhcp && !options[:ip]
|
260
268
|
# Try to find a matching device to set the config ip to
|
261
269
|
matching_device = hostonly_find_matching_network(options)
|
@@ -263,7 +271,7 @@ module VagrantPlugins
|
|
263
271
|
options[:ip] = matching_device[:ip]
|
264
272
|
else
|
265
273
|
# Default IP is in the 20-bit private network block for DHCP based networks
|
266
|
-
options[:ip] = "
|
274
|
+
options[:ip] = "192.168.56.1"
|
267
275
|
end
|
268
276
|
end
|
269
277
|
|
@@ -288,6 +296,8 @@ module VagrantPlugins
|
|
288
296
|
error: e.message
|
289
297
|
end
|
290
298
|
|
299
|
+
validate_hostonly_ip!(options[:ip], @env[:machine].provider.driver)
|
300
|
+
|
291
301
|
if ip.ipv4?
|
292
302
|
# Verify that a host-only network subnet would not collide
|
293
303
|
# with a bridged networking interface.
|
@@ -501,6 +511,33 @@ module VagrantPlugins
|
|
501
511
|
nil
|
502
512
|
end
|
503
513
|
|
514
|
+
# Validates the IP used to configure the network is within the allowed
|
515
|
+
# ranges. It only validates if the network configuration file exists.
|
516
|
+
# This was introduced in 6.1.28 so previous version won't have restrictions
|
517
|
+
# placed on the valid ranges
|
518
|
+
def validate_hostonly_ip!(ip, driver)
|
519
|
+
return if Gem::Version.new(driver.version) < HOSTONLY_VALIDATE_VERSION ||
|
520
|
+
Vagrant::Util::Platform.windows?
|
521
|
+
|
522
|
+
ip = IPAddr.new(ip.to_s) if !ip.is_a?(IPAddr)
|
523
|
+
valid_ranges = load_net_conf
|
524
|
+
return if valid_ranges.any?{ |range| range.include?(ip) }
|
525
|
+
raise Vagrant::Errors::VirtualBoxInvalidHostSubnet,
|
526
|
+
address: ip,
|
527
|
+
ranges: valid_ranges.map{ |r| "#{r}/#{r.prefix}" }.join(", ")
|
528
|
+
end
|
529
|
+
|
530
|
+
def load_net_conf
|
531
|
+
return HOSTONLY_DEFAULT_RANGE if !File.exist?(VBOX_NET_CONF)
|
532
|
+
File.readlines(VBOX_NET_CONF).map do |line|
|
533
|
+
line = line.strip
|
534
|
+
next if !line.start_with?("*")
|
535
|
+
line[1,line.length].strip.split(" ").map do |entry|
|
536
|
+
IPAddr.new(entry)
|
537
|
+
end
|
538
|
+
end.flatten.compact
|
539
|
+
end
|
540
|
+
|
504
541
|
#-----------------------------------------------------------------
|
505
542
|
# DHCP Server Helper Functions
|
506
543
|
#-----------------------------------------------------------------
|
@@ -6,11 +6,13 @@ module VagrantPlugins
|
|
6
6
|
# Check if Chef is installed at the given version.
|
7
7
|
# @return [true, false]
|
8
8
|
def self.chef_installed(machine, product, version)
|
9
|
-
|
10
|
-
|
9
|
+
product_name = product == 'chef-workstation' ? 'chef-workstation' : 'chef'
|
10
|
+
verify_bin = product_name == 'chef-workstation' ? 'chef' : 'chef-client'
|
11
|
+
verify_path = "/opt/#{product_name}/bin/#{verify_bin}"
|
12
|
+
command = "test -x #{verify_path}"
|
11
13
|
|
12
14
|
if version != :latest
|
13
|
-
command << "&& #{
|
15
|
+
command << "&& #{verify_path} --version | grep '#{version}'"
|
14
16
|
end
|
15
17
|
|
16
18
|
machine.communicate.test(command, sudo: true)
|
@@ -6,11 +6,13 @@ module VagrantPlugins
|
|
6
6
|
# Check if Chef is installed at the given version.
|
7
7
|
# @return [true, false]
|
8
8
|
def self.chef_installed(machine, product, version)
|
9
|
-
|
10
|
-
|
9
|
+
product_name = product == 'chef-workstation' ? 'chef-workstation' : 'chef'
|
10
|
+
verify_bin = product_name == 'chef-workstation' ? 'chef' : 'chef-client'
|
11
|
+
verify_path = "/opt/#{product_name}/bin/#{verify_bin}"
|
12
|
+
command = "test -x #{verify_path}"
|
11
13
|
|
12
14
|
if version != :latest
|
13
|
-
command << "&& #{
|
15
|
+
command << "&& #{verify_path} --version | grep '#{version}'"
|
14
16
|
end
|
15
17
|
|
16
18
|
machine.communicate.test(command, sudo: true)
|
@@ -2,19 +2,21 @@ module VagrantPlugins
|
|
2
2
|
module Chef
|
3
3
|
module Cap
|
4
4
|
module OmniOS
|
5
|
-
module ChefInstalled
|
5
|
+
module ChefInstalled
|
6
6
|
# TODO: this is the same code as cap/linux/chef_installed, consider merging
|
7
7
|
# Check if Chef is installed at the given version.
|
8
8
|
# @return [true, false]
|
9
9
|
def self.chef_installed(machine, product, version)
|
10
|
-
|
11
|
-
|
10
|
+
product_name = product == 'chef-workstation' ? 'chef-workstation' : 'chef'
|
11
|
+
verify_bin = product_name == 'chef-workstation' ? 'chef' : 'chef-client'
|
12
|
+
verify_path = "/opt/#{product_name}/bin/#{verify_bin}"
|
13
|
+
command = "test -x #{verify_path}"
|
12
14
|
|
13
15
|
if version != :latest
|
14
|
-
command << "&& #{
|
16
|
+
command << "&& #{verify_path} --version | grep '#{version}'"
|
15
17
|
end
|
16
18
|
|
17
|
-
machine.communicate.test(command, sudo: true)
|
19
|
+
machine.communicate.test(command, sudo: true)
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -6,10 +6,11 @@ module VagrantPlugins
|
|
6
6
|
# Check if Chef is installed at the given version.
|
7
7
|
# @return [true, false]
|
8
8
|
def self.chef_installed(machine, product, version)
|
9
|
+
verify_bin = product == 'chef-workstation' ? 'chef' : 'chef-client'
|
9
10
|
if version != :latest
|
10
|
-
command = 'if ((&
|
11
|
+
command = 'if ((&' + verify_bin + ' --version) -Match "' + version.to_s + '"){ exit 0 } else { exit 1 }'
|
11
12
|
else
|
12
|
-
command = 'if ((&
|
13
|
+
command = 'if ((&' + verify_bin + ' --version) -Match "Chef*"){ exit 0 } else { exit 1 }'
|
13
14
|
end
|
14
15
|
machine.communicate.test(command, sudo: true)
|
15
16
|
end
|
data/templates/locales/en.yml
CHANGED
@@ -845,6 +845,19 @@ en:
|
|
845
845
|
create_iso_host_cap_not_found: |-
|
846
846
|
Vagrant cannot create an iso due to the host capability for creating isos not existing.
|
847
847
|
Vagrant will now exit.
|
848
|
+
darwin_mount_failed: |-
|
849
|
+
Failed to mount folders in Darwin guest. The command attempted was:
|
850
|
+
|
851
|
+
%{command}
|
852
|
+
|
853
|
+
The error output from the last command was:
|
854
|
+
|
855
|
+
%{output}
|
856
|
+
darwin_version_failed: |-
|
857
|
+
Failed to determine macOS version.
|
858
|
+
|
859
|
+
Version string: %{version}
|
860
|
+
Error information: %{error}
|
848
861
|
destroy_requires_force: |-
|
849
862
|
Destroy doesn't have a TTY to ask for confirmation. Please pass the
|
850
863
|
`--force` flag to force a destroy, otherwise attach a TTY so that
|
@@ -1842,6 +1855,18 @@ en:
|
|
1842
1855
|
outputted:
|
1843
1856
|
|
1844
1857
|
%{vboxmanage} --version
|
1858
|
+
virtualbox_invalid_host_subnet: |-
|
1859
|
+
The IP address configured for the host-only network is not within the
|
1860
|
+
allowed ranges. Please update the address used to be within the allowed
|
1861
|
+
ranges and run the command again.
|
1862
|
+
|
1863
|
+
Address: %{address}
|
1864
|
+
Ranges: %{ranges}
|
1865
|
+
|
1866
|
+
Valid ranges can be modified in the /etc/vbox/networks.conf file. For
|
1867
|
+
more information including valid format see:
|
1868
|
+
|
1869
|
+
https://www.virtualbox.org/manual/ch06.html#network_hostonly
|
1845
1870
|
vm_creation_required: |-
|
1846
1871
|
VM must be created before running this command. Run `vagrant up` first.
|
1847
1872
|
vm_inaccessible: |-
|
data/vagrant.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.add_dependency "erubi"
|
21
21
|
s.add_dependency "hashicorp-checkpoint", "~> 0.1.5"
|
22
22
|
s.add_dependency "i18n", "~> 1.8"
|
23
|
-
s.add_dependency "listen", "~> 3.
|
23
|
+
s.add_dependency "listen", "~> 3.6"
|
24
24
|
s.add_dependency "log4r", "~> 1.1.9", "< 1.1.11"
|
25
25
|
s.add_dependency "mime-types", "~> 3.3"
|
26
26
|
s.add_dependency "net-ssh", ">= 6.1.0", "< 6.2"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
## Getting Involved
|
2
|
+
|
3
|
+
New contributors are always welcome, when it doubt please ask questions. We strive to be an open and welcoming community. Please be nice to one another.
|
4
|
+
|
5
|
+
### Coding
|
6
|
+
|
7
|
+
* Pick a task:
|
8
|
+
* Offer feedback on open [pull requests](https://github.com/excon/excon/pulls).
|
9
|
+
* Review open [issues](https://github.com/excon/excon/issues) for things to help on.
|
10
|
+
* [Create an issue](https://github.com/excon/excon/issues/new) to start a discussion on additions or features.
|
11
|
+
* Fork the project, add your changes and tests to cover them in a topic branch.
|
12
|
+
* Commit your changes and rebase against `excon/excon` to ensure everything is up to date.
|
13
|
+
* [Submit a pull request](https://github.com/excon/excon/compare/).
|
14
|
+
|
15
|
+
### Non-Coding
|
16
|
+
|
17
|
+
* Work for [twitter](http://twitter.com)? I'd love to reclaim the unused [@excon](http://twitter.com/excon) account!
|
18
|
+
* Offer feedback on open [issues](https://github.com/excon/excon/issues).
|
19
|
+
* Write and help edit [documentation](https://github.com/excon/excon.github.com).
|
20
|
+
* Translate [documentation](https://github.com/excon/excon.github.com) in to other languages.
|
21
|
+
* Organize or volunteer at events.
|
22
|
+
* [Donate](https://www.gittip.com/geemus/)!
|
23
|
+
* Discuss other ideas for contribution with [geemus](mailto:geemus+excon@gmail.com).
|