vagrant-docker-networks-manager 0.1.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 +7 -0
- data/CHANGELOG.md +16 -0
- data/LICENSE.md +22 -0
- data/README.md +320 -0
- data/lib/vagrant-docker-networks-manager/VERSION +1 -0
- data/lib/vagrant-docker-networks-manager/action.rb +204 -0
- data/lib/vagrant-docker-networks-manager/command.rb +553 -0
- data/lib/vagrant-docker-networks-manager/config.rb +164 -0
- data/lib/vagrant-docker-networks-manager/helpers.rb +98 -0
- data/lib/vagrant-docker-networks-manager/network_builder.rb +44 -0
- data/lib/vagrant-docker-networks-manager/plugin.rb +33 -0
- data/lib/vagrant-docker-networks-manager/util.rb +152 -0
- data/lib/vagrant-docker-networks-manager/version.rb +10 -0
- data/lib/vagrant-docker-networks-manager.rb +4 -0
- data/locales/en.yml +142 -0
- data/locales/fr.yml +142 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a02b353f50a855257d0e7e7f72279b47666e4f6131c2b621a3d58d3b6a4780ed
|
4
|
+
data.tar.gz: 3a2ac68c851a9b6c54ed3aec26c7394086013ac902dcafa19fcc245d6a5da23d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9d61692ed4dcfd31642630109b346c3c13d7d3adc13473a2a777c5add55f5cdb4b56e29992f72a49d1af59e4915c06c039a4cc0d186bcc6a7867c3eb0f1b50d6
|
7
|
+
data.tar.gz: 30c99e6849d84e5ba1d2fe5d378bd195be123e7fad9c55addc3369ddc612d7ff98a73ce7e45a239aebe5f4853576892d330eaacb0082d7cf361edd24b0675f73
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [0.1.1](https://github.com/julienpoirou/vagrant-docker-networks-manager/compare/v0.1.0...v0.1.1) (2025-08-17)
|
4
|
+
|
5
|
+
|
6
|
+
### CI 🧑‍💻
|
7
|
+
|
8
|
+
* **release-please:** Add issues:write permission ([1c959e0](https://github.com/julienpoirou/vagrant-docker-networks-manager/commit/1c959e04ac86bc7a81363cf4029e0dc52acfc5f7))
|
9
|
+
* **release-please:** Point to dotfiles config ([d123be2](https://github.com/julienpoirou/vagrant-docker-networks-manager/commit/d123be274d8aac8d4f2de2de40df976b58f29a2e))
|
10
|
+
* **release-please:** Use generic updater for VERSION file ([#3](https://github.com/julienpoirou/vagrant-docker-networks-manager/issues/3)) ([1cc3003](https://github.com/julienpoirou/vagrant-docker-networks-manager/commit/1cc30033cef9b8be87255c45dd82a1ebe1877e7f))
|
11
|
+
|
12
|
+
|
13
|
+
### Maintenance đź§ą
|
14
|
+
|
15
|
+
* **ci:** Unblock CI => RSpec shim & RuboCop config baseline ([#1](https://github.com/julienpoirou/vagrant-docker-networks-manager/issues/1)) ([2e4a1df](https://github.com/julienpoirou/vagrant-docker-networks-manager/commit/2e4a1df9d0d46063c908765d7fbfd17a55fe3f9a))
|
16
|
+
* **init:** Bootstrap plugin, CI, CodeQL, Release, Docs ([2b71a69](https://github.com/julienpoirou/vagrant-docker-networks-manager/commit/2b71a69e2b1eb1dd87cdf75b6e9ed1c350afd366))
|
data/LICENSE.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
===========
|
3
|
+
|
4
|
+
Copyright (c) 2025 Julien Poirou <julienpoirou@protonmail.com>
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the “Software”), to deal
|
8
|
+
in the Software without restriction, including without limitation the rights
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
14
|
+
all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,320 @@
|
|
1
|
+
# vagrant-docker-networks-manager
|
2
|
+
|
3
|
+
[](https://github.com/julienpoirou/vagrant-docker-networks-manager/actions/workflows/ci.yml)
|
4
|
+
[](https://github.com/julienpoirou/vagrant-docker-networks-manager/actions/workflows/codeql.yml)
|
5
|
+
[](https://github.com/julienpoirou/vagrant-docker-networks-manager/releases)
|
6
|
+
[](https://rubygems.org/gems/vagrant-docker-networks-manager)
|
7
|
+
[](LICENSE.md)
|
8
|
+
[](https://www.conventionalcommits.org)
|
9
|
+
[](https://renovatebot.com)
|
10
|
+
|
11
|
+
Vagrant plugin to **manage Docker networks** with labeled ownership, safe lifecycle hooks, JSON output, and conflict-aware validation.
|
12
|
+
|
13
|
+
- Creates a Docker network on `vagrant up` (with labels & marker)
|
14
|
+
- Cleans it on `vagrant destroy` **only if owned by this machine** (safe)
|
15
|
+
- `vagrant network` CLI: `init | destroy | info | reload | list | prune | rename`
|
16
|
+
- IPv4/CIDR validation, subnet conflict detection, optional macvlan
|
17
|
+
- i18n (English 🇬🇧 / Français 🇫🇷), emojis, and normalized JSON output
|
18
|
+
|
19
|
+
> Requirements: **Vagrant ≥ 2.2**, **Ruby ≥ 3.1**, **Docker (CLI + daemon) running**
|
20
|
+
|
21
|
+
---
|
22
|
+
|
23
|
+
## Table of contents
|
24
|
+
|
25
|
+
- [Why this plugin?](#why-this-plugin)
|
26
|
+
- [Installation](#installation)
|
27
|
+
- [Quick start](#quick-start)
|
28
|
+
- [Vagrantfile configuration](#vagrantfile-configuration)
|
29
|
+
- [CLI usage](#cli-usage)
|
30
|
+
- [JSON output examples](#json-output-examples)
|
31
|
+
- [Ownership & safety](#ownership--safety)
|
32
|
+
- [Subnet validation & conflicts](#subnet-validation--conflicts)
|
33
|
+
- [Internationalization](#internationalization)
|
34
|
+
- [Environment variables](#environment-variables)
|
35
|
+
- [Permissions & OS notes](#permissions--os-notes)
|
36
|
+
- [Troubleshooting](#troubleshooting)
|
37
|
+
- [Contributing & Development](#contributing--development)
|
38
|
+
- [License](#license)
|
39
|
+
|
40
|
+
> 🇫🇷 **Français :** voir [README.fr.md](README.fr.md)
|
41
|
+
|
42
|
+
---
|
43
|
+
|
44
|
+
## Why this plugin?
|
45
|
+
|
46
|
+
Managing Docker networks across Vagrant projects is tedious:
|
47
|
+
|
48
|
+
- naming consistency, subnet overlaps, and safe cleanup are error-prone
|
49
|
+
- destroying a VM shouldn’t delete someone else’s shared network
|
50
|
+
- operators need deterministic CLI **and** machine-readable output
|
51
|
+
|
52
|
+
This plugin solves these by **labeling** networks, keeping a **marker** per machine, validating **CIDR** + detecting **overlaps**, and offering a clean **CLI** with **JSON** output.
|
53
|
+
|
54
|
+
---
|
55
|
+
|
56
|
+
## Installation
|
57
|
+
|
58
|
+
From RubyGems (once published):
|
59
|
+
|
60
|
+
```bash
|
61
|
+
vagrant plugin install vagrant-docker-networks-manager
|
62
|
+
```
|
63
|
+
|
64
|
+
From source (local path):
|
65
|
+
|
66
|
+
```bash
|
67
|
+
git clone https://github.com/julienpoirou/vagrant-docker-networks-manager
|
68
|
+
cd vagrant-docker-networks-manager
|
69
|
+
bundle install
|
70
|
+
rake
|
71
|
+
vagrant plugin install . # install from the local gemspec
|
72
|
+
```
|
73
|
+
|
74
|
+
Check it’s available:
|
75
|
+
|
76
|
+
```bash
|
77
|
+
vagrant network version
|
78
|
+
vagrant network help
|
79
|
+
```
|
80
|
+
|
81
|
+
---
|
82
|
+
|
83
|
+
## Quick start
|
84
|
+
|
85
|
+
### Minimal Vagrantfile
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
Vagrant.configure("2") do |config|
|
89
|
+
config.vm.box = "hashicorp/ubuntu-22.04"
|
90
|
+
|
91
|
+
# Docker network plugin config
|
92
|
+
config.docker_network.network_name = "myproj_net" # ⚠️ personalize to avoid collisions
|
93
|
+
config.docker_network.network_subnet = "172.28.50.0/24"
|
94
|
+
config.docker_network.network_gateway = "172.28.50.1"
|
95
|
+
config.docker_network.network_type = "bridge" # or "macvlan"
|
96
|
+
config.docker_network.network_parent = nil # required if macvlan
|
97
|
+
config.docker_network.network_attachable = true
|
98
|
+
config.docker_network.enable_ipv6 = false
|
99
|
+
config.docker_network.ip_range = nil # optional
|
100
|
+
config.docker_network.cleanup_on_destroy = true
|
101
|
+
config.docker_network.locale = "en" # "en" or "fr"
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
### Create the network on `up`
|
106
|
+
|
107
|
+
```bash
|
108
|
+
vagrant up
|
109
|
+
```
|
110
|
+
|
111
|
+
If a network with the same name already exists:
|
112
|
+
- if it’s **owned** by this machine (labels match), it’s “adopted”
|
113
|
+
- otherwise you simply get an info message (no destructive action)
|
114
|
+
|
115
|
+
### Destroy VM and clean the network
|
116
|
+
|
117
|
+
```bash
|
118
|
+
vagrant destroy
|
119
|
+
```
|
120
|
+
|
121
|
+
- The network is removed **only** if created/owned by this machine.
|
122
|
+
- To also remove attached containers during Vagrant destroy:
|
123
|
+
|
124
|
+
```bash
|
125
|
+
VDNM_DESTROY_WITH_CONTAINERS=1 vagrant destroy
|
126
|
+
```
|
127
|
+
|
128
|
+
---
|
129
|
+
|
130
|
+
## Vagrantfile configuration
|
131
|
+
|
132
|
+
All options (with defaults):
|
133
|
+
|
134
|
+
| Key | Type | Default | Notes |
|
135
|
+
|----------------------------|---------|--------------------|-------|
|
136
|
+
| `network_name` | String | `"network_lo1"` | ⚠️ Personalize to avoid collisions across projects. |
|
137
|
+
| `network_subnet` | String | `"172.28.100.0/26"`| Must be **aligned** IPv4/CIDR (e.g. `x.y.z.0/nn`). |
|
138
|
+
| `network_type` | String | `"bridge"` | `"bridge"` or `"macvlan"`. |
|
139
|
+
| `network_gateway` | String | `"172.28.100.1"` | Must be a **host** address inside `network_subnet`. |
|
140
|
+
| `network_parent` | String | `nil` | **Required** if `network_type == "macvlan"`. |
|
141
|
+
| `network_attachable` | Bool | `false` | Adds `--attachable`. |
|
142
|
+
| `enable_ipv6` | Bool | `false` | Adds `--ipv6`. |
|
143
|
+
| `ip_range` | String | `nil` | IPv4/CIDR **inside** `network_subnet`. |
|
144
|
+
| `cleanup_on_destroy` | Bool | `true` | Remove network on `vagrant destroy` if owned/created. |
|
145
|
+
| `locale` | String | `"en"` | `"en"` or `"fr"`. |
|
146
|
+
|
147
|
+
Validation performed:
|
148
|
+
- Docker name constraints, aligned IPv4/CIDR, `gateway` not network/broadcast
|
149
|
+
- `ip_range` must be included in `network_subnet`
|
150
|
+
- `macvlan` requires `network_parent`
|
151
|
+
|
152
|
+
---
|
153
|
+
|
154
|
+
## CLI usage
|
155
|
+
|
156
|
+
```
|
157
|
+
vagrant network <command> [args] [options]
|
158
|
+
|
159
|
+
Commands:
|
160
|
+
init <name> <subnet>
|
161
|
+
destroy <name> [--with-containers] [--yes]
|
162
|
+
reload <name> [--yes]
|
163
|
+
info <name>
|
164
|
+
list [--json]
|
165
|
+
prune [--yes]
|
166
|
+
rename <old> <new> [<subnet>] [--yes]
|
167
|
+
|
168
|
+
Global options:
|
169
|
+
--json # machine-readable output
|
170
|
+
--yes, -y # auto-confirm prompts
|
171
|
+
--quiet # reduce output (hide info)
|
172
|
+
--no-emoji # disable emojis
|
173
|
+
--lang en|fr # force language
|
174
|
+
```
|
175
|
+
|
176
|
+
Examples:
|
177
|
+
|
178
|
+
```bash
|
179
|
+
vagrant network init mynet 172.28.100.0/26
|
180
|
+
vagrant network info mynet
|
181
|
+
vagrant network list
|
182
|
+
vagrant network destroy mynet --with-containers --yes
|
183
|
+
vagrant network reload mynet --yes
|
184
|
+
vagrant network rename oldnet newnet --yes
|
185
|
+
vagrant network rename oldnet same-name 10.10.0.0/24 --yes
|
186
|
+
vagrant network prune --yes
|
187
|
+
```
|
188
|
+
|
189
|
+
---
|
190
|
+
|
191
|
+
## JSON output examples
|
192
|
+
|
193
|
+
Enable with `--json` for any command.
|
194
|
+
|
195
|
+
**init**
|
196
|
+
```json
|
197
|
+
{"action":"init","status":"success","data":{"name":"mynet","subnet":"172.28.100.0/26"}}
|
198
|
+
```
|
199
|
+
|
200
|
+
**info**
|
201
|
+
```json
|
202
|
+
{
|
203
|
+
"action":"info",
|
204
|
+
"status":"success",
|
205
|
+
"data":{
|
206
|
+
"network":{
|
207
|
+
"Name":"mynet",
|
208
|
+
"Id":"...docker-id...",
|
209
|
+
"Driver":"bridge",
|
210
|
+
"Subnets":["172.28.100.0/26"],
|
211
|
+
"Containers":[{"Name":"web","IPv4":"172.28.100.2/26"}]
|
212
|
+
}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
```
|
216
|
+
|
217
|
+
**prune (nothing to do)**
|
218
|
+
```json
|
219
|
+
{"action":"prune","status":"success","data":{"pruned":0,"items":[]}}
|
220
|
+
```
|
221
|
+
|
222
|
+
Errors are normalized:
|
223
|
+
```json
|
224
|
+
{"action":"destroy","status":"error","error":"Network not found.","data":{"name":"ghost"}, "code":1}
|
225
|
+
```
|
226
|
+
|
227
|
+
---
|
228
|
+
|
229
|
+
## Ownership & safety
|
230
|
+
|
231
|
+
- Networks are created with labels:
|
232
|
+
- `com.vagrant.plugin=docker_networks_manager`
|
233
|
+
- `com.vagrant.machine_id=<VAGRANT_MACHINE_ID>`
|
234
|
+
- A **marker file** is also written in:
|
235
|
+
`.vagrant/machines/<name>/<provider>/docker-networks/<network>.json`
|
236
|
+
|
237
|
+
On `vagrant destroy`, the plugin **only removes** a network if:
|
238
|
+
- the marker indicates it was created by this machine, **or**
|
239
|
+
- labels match this machine’s id (ownership)
|
240
|
+
|
241
|
+
If a network exists but is not owned, the plugin leaves it untouched.
|
242
|
+
|
243
|
+
---
|
244
|
+
|
245
|
+
## Subnet validation & conflicts
|
246
|
+
|
247
|
+
Before creating (or renaming to a new subnet), the plugin:
|
248
|
+
|
249
|
+
1. Validates `network_subnet` is an **aligned IPv4/CIDR**
|
250
|
+
(e.g. `172.28.100.0/24`, not `172.28.100.1/24`)
|
251
|
+
2. Scans existing Docker networks and checks for **overlaps**
|
252
|
+
(ignoring the target network when appropriate)
|
253
|
+
|
254
|
+
This prevents hard-to-debug IP conflicts.
|
255
|
+
|
256
|
+
---
|
257
|
+
|
258
|
+
## Internationalization
|
259
|
+
|
260
|
+
- Locales: **en**, **fr**
|
261
|
+
- Choose via CLI `--lang en|fr`, or set `locale` in your Vagrantfile, or `VDNM_LANG=en|fr`.
|
262
|
+
|
263
|
+
Emojis can be disabled with `--no-emoji`.
|
264
|
+
|
265
|
+
---
|
266
|
+
|
267
|
+
## Environment variables
|
268
|
+
|
269
|
+
| Variable | Purpose |
|
270
|
+
|----------------------------------|---------|
|
271
|
+
| `VDNM_LANG` | Force locale (`en`/`fr`) in hooks. |
|
272
|
+
| `VDNM_VERBOSE` | When `1`, prints the full `docker` command on STDERR and shows the native Docker output. |
|
273
|
+
| `VDNM_SKIP_CONFLICTS` | When `1`, the reload ignores subnet conflict detection (dangerous, for experts only). |
|
274
|
+
| `VDNM_DESTROY_WITH_CONTAINERS` | When `1`, on Vagrant destroy the plugin also runs `docker rm -f` for attached containers (in addition to disconnect). |
|
275
|
+
|
276
|
+
> The CLI `vagrant network destroy <name> --with-containers` achieves the same for the **manual command**.
|
277
|
+
|
278
|
+
---
|
279
|
+
|
280
|
+
## Permissions & OS notes
|
281
|
+
|
282
|
+
- **Linux / macOS**: modifying `/etc/hosts` requires privileges. The plugin pipes through `sudo tee -a` when appending, and writes the file when removing. You may be prompted for your password.
|
283
|
+
- **Windows**: the plugin uses **PowerShell elevation** (`Start-Process -Verb RunAs`) when needed to append or rewrite the hosts file.
|
284
|
+
|
285
|
+
> If your shell is already elevated (root/Admin), no prompts appear.
|
286
|
+
|
287
|
+
---
|
288
|
+
|
289
|
+
## Troubleshooting
|
290
|
+
|
291
|
+
- **Docker is unavailable**: ensure Docker Desktop/daemon is running and the CLI works (`docker info`).
|
292
|
+
- **Invalid subnet**: use aligned IPv4/CIDR (e.g. `10.0.0.0/24`).
|
293
|
+
- **Subnet already in use**: another network overlaps. Pick a different range.
|
294
|
+
- **Remove failed**: some containers or other constraints may block `docker network rm`. Try `--verbose` (`VDNM_VERBOSE=1`) to see Docker’s output.
|
295
|
+
- **macvlan**: remember to set `network_parent` (host interface).
|
296
|
+
|
297
|
+
---
|
298
|
+
|
299
|
+
## Contributing & Development
|
300
|
+
|
301
|
+
```bash
|
302
|
+
git clone https://github.com/julienpoirou/vagrant-docker-networks-manager
|
303
|
+
cd vagrant-docker-networks-manager
|
304
|
+
bundle install
|
305
|
+
rake # runs RSpec
|
306
|
+
```
|
307
|
+
|
308
|
+
- Conventional Commits enforced in PRs.
|
309
|
+
- CI runs RuboCop, tests, and builds the gem.
|
310
|
+
- See `docs/en/CONTRIBUTING.md` and `docs/en/DEVELOPMENT.md` if present.
|
311
|
+
|
312
|
+
---
|
313
|
+
|
314
|
+
## License
|
315
|
+
|
316
|
+
MIT © 2025 [Julien Poirou](mailto:julienpoirou@protonmail.com)
|
317
|
+
|
318
|
+
---
|
319
|
+
|
320
|
+
> Tip: prefer setting a **project-specific** `network_name` (e.g. `myapp_net`) to avoid collisions if multiple Vagrant projects run on the same host.
|
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "fileutils"
|
5
|
+
require "time"
|
6
|
+
require "shellwords"
|
7
|
+
require "open3"
|
8
|
+
require_relative "helpers"
|
9
|
+
require_relative "util"
|
10
|
+
require_relative "network_builder"
|
11
|
+
require_relative "version"
|
12
|
+
|
13
|
+
module VagrantDockerNetworksManager
|
14
|
+
class ActionUp
|
15
|
+
def initialize(app, _env); @app = app; end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
UiHelpers.setup_i18n!
|
19
|
+
cfg = env[:machine].config.docker_network
|
20
|
+
set_locale!(cfg)
|
21
|
+
|
22
|
+
unless Util.docker_available?
|
23
|
+
env[:ui].error("#{UiHelpers.e(:error)} #{I18n.t('errors.docker_unavailable')}")
|
24
|
+
return @app.call(env)
|
25
|
+
end
|
26
|
+
|
27
|
+
name = cfg.network_name
|
28
|
+
mid = env[:machine].id
|
29
|
+
|
30
|
+
if Util.docker_network_exists?(name)
|
31
|
+
if owned_by_this_machine?(name, mid)
|
32
|
+
write_marker(env, name, cfg)
|
33
|
+
env[:ui].info("#{UiHelpers.e(:success)} #{I18n.t('messages.network_exists_adopted', name: name)}")
|
34
|
+
else
|
35
|
+
env[:ui].info("#{UiHelpers.e(:info)} #{I18n.t('messages.network_exists', name: name)}")
|
36
|
+
end
|
37
|
+
else
|
38
|
+
subnet_label = cfg.network_subnet || "-"
|
39
|
+
|
40
|
+
if cfg.network_subnet && !VagrantDockerNetworksManager::Util.valid_subnet?(cfg.network_subnet)
|
41
|
+
env[:ui].error("#{UiHelpers.e(:error)} #{I18n.t('errors.invalid_subnet')}")
|
42
|
+
return @app.call(env)
|
43
|
+
end
|
44
|
+
|
45
|
+
if cfg.network_subnet &&
|
46
|
+
VagrantDockerNetworksManager::Util.docker_subnet_conflicts?(
|
47
|
+
cfg.network_subnet,
|
48
|
+
ignore_network: name
|
49
|
+
)
|
50
|
+
env[:ui].error("#{UiHelpers.e(:error)} #{I18n.t('errors.subnet_in_use')}")
|
51
|
+
return @app.call(env)
|
52
|
+
end
|
53
|
+
|
54
|
+
env[:ui].info("#{UiHelpers.e(:ongoing)} #{I18n.t('log.create_network', name: name, subnet: subnet_label)}")
|
55
|
+
builder = NetworkBuilder.new(cfg, machine_id: mid)
|
56
|
+
args = builder.build_create_command_args
|
57
|
+
if Util.sh!(*args)
|
58
|
+
write_marker(env, name, cfg)
|
59
|
+
env[:ui].info("#{UiHelpers.e(:success)} #{I18n.t('log.ok')}")
|
60
|
+
else
|
61
|
+
rendered = args.shelljoin
|
62
|
+
env[:ui].error("#{UiHelpers.e(:error)} #{I18n.t('messages.create_failed', cmd: rendered)}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
@app.call(env)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def set_locale!(cfg)
|
72
|
+
lang = cfg.locale || ENV["VDNM_LANG"]
|
73
|
+
return unless lang
|
74
|
+
UiHelpers.set_locale!(lang)
|
75
|
+
rescue UiHelpers::UnsupportedLocaleError
|
76
|
+
UiHelpers.set_locale!("en")
|
77
|
+
end
|
78
|
+
|
79
|
+
def write_marker(env, name, cfg)
|
80
|
+
m_id = env[:machine].id
|
81
|
+
dir = env[:machine].data_dir.join("docker-networks")
|
82
|
+
FileUtils.mkdir_p(dir)
|
83
|
+
marker = dir.join("#{name}.json")
|
84
|
+
payload = {
|
85
|
+
"name" => name,
|
86
|
+
"machine_id" => m_id,
|
87
|
+
"plugin" => "vagrant-docker-networks-manager",
|
88
|
+
"version" => VagrantDockerNetworksManager::VERSION,
|
89
|
+
"created_at" => Time.now.utc.iso8601,
|
90
|
+
"config" => {
|
91
|
+
"type" => cfg.network_type,
|
92
|
+
"subnet" => cfg.network_subnet,
|
93
|
+
"gateway" => cfg.network_gateway,
|
94
|
+
"ip_range" => cfg.ip_range,
|
95
|
+
"ipv6" => !!cfg.enable_ipv6,
|
96
|
+
"attachable" => !!cfg.network_attachable,
|
97
|
+
"parent" => cfg.network_parent
|
98
|
+
}
|
99
|
+
}
|
100
|
+
File.write(marker, JSON.pretty_generate(payload))
|
101
|
+
rescue => e
|
102
|
+
env[:ui].warn("marker write failed for '#{name}': #{e.message}")
|
103
|
+
end
|
104
|
+
|
105
|
+
def owned_by_this_machine?(name, machine_id)
|
106
|
+
labels = Util.read_network_labels(name)
|
107
|
+
labels["com.vagrant.plugin"] == "docker_networks_manager" &&
|
108
|
+
labels["com.vagrant.machine_id"] == machine_id
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class ActionDestroy
|
113
|
+
def initialize(app, _env); @app = app; end
|
114
|
+
|
115
|
+
def call(env)
|
116
|
+
UiHelpers.setup_i18n!
|
117
|
+
cfg = env[:machine].config.docker_network
|
118
|
+
set_locale!(cfg)
|
119
|
+
|
120
|
+
unless Util.docker_available?
|
121
|
+
env[:ui].error("#{UiHelpers.e(:error)} #{I18n.t('errors.docker_unavailable')}")
|
122
|
+
return @app.call(env)
|
123
|
+
end
|
124
|
+
|
125
|
+
name = cfg.network_name
|
126
|
+
mid = env[:machine].id
|
127
|
+
|
128
|
+
unless cfg.cleanup_on_destroy
|
129
|
+
@app.call(env)
|
130
|
+
return
|
131
|
+
end
|
132
|
+
|
133
|
+
if created_by_this_machine?(env, name) || owned_by_this_machine?(name, mid)
|
134
|
+
env[:ui].info("#{UiHelpers.e(:broom)} #{I18n.t('messages.remove_network', name: name)}")
|
135
|
+
|
136
|
+
if Util.docker_network_exists?(name)
|
137
|
+
out, _e, st = Open3.capture3("docker", "network", "inspect", name)
|
138
|
+
if st.success?
|
139
|
+
begin
|
140
|
+
info = JSON.parse(out).first
|
141
|
+
(info["Containers"] || {}).values.each do |c|
|
142
|
+
cn = c["Name"]
|
143
|
+
env[:ui].info("#{UiHelpers.e(:ongoing)} #{I18n.t('log.disconnect_container', name: cn)}")
|
144
|
+
Util.sh!("network", "disconnect", "--force", name, cn)
|
145
|
+
if ENV["VDNM_DESTROY_WITH_CONTAINERS"] == "1"
|
146
|
+
env[:ui].info("#{UiHelpers.e(:ongoing)} #{I18n.t('log.remove_container', name: cn)}")
|
147
|
+
Util.sh!("rm", "-f", cn)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
rescue => e
|
151
|
+
env[:ui].warn("failed to parse containers for '#{name}': #{e.message}")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
if Util.sh!("network", "rm", name)
|
156
|
+
delete_marker(env, name)
|
157
|
+
env[:ui].info("#{UiHelpers.e(:success)} #{I18n.t('log.ok')}")
|
158
|
+
else
|
159
|
+
env[:ui].warn("#{UiHelpers.e(:warning)} #{I18n.t('errors.remove_failed')}")
|
160
|
+
end
|
161
|
+
else
|
162
|
+
delete_marker(env, name)
|
163
|
+
env[:ui].info("#{UiHelpers.e(:info)} #{I18n.t('messages.nothing_to_do')}")
|
164
|
+
end
|
165
|
+
else
|
166
|
+
env[:ui].info("#{UiHelpers.e(:broom)} #{I18n.t('messages.nothing_to_do')}")
|
167
|
+
end
|
168
|
+
|
169
|
+
@app.call(env)
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def set_locale!(cfg)
|
175
|
+
lang = cfg.locale || ENV["VDNM_LANG"]
|
176
|
+
return unless lang
|
177
|
+
UiHelpers.set_locale!(lang)
|
178
|
+
rescue UiHelpers::UnsupportedLocaleError
|
179
|
+
UiHelpers.set_locale!("en")
|
180
|
+
end
|
181
|
+
|
182
|
+
def marker_path(env, name)
|
183
|
+
env[:machine].data_dir.join("docker-networks", "#{name}.json")
|
184
|
+
end
|
185
|
+
|
186
|
+
def created_by_this_machine?(env, name)
|
187
|
+
marker = marker_path(env, name)
|
188
|
+
return false unless File.exist?(marker)
|
189
|
+
j = JSON.parse(File.read(marker)) rescue {}
|
190
|
+
j["name"] == name && j["machine_id"] == env[:machine].id
|
191
|
+
end
|
192
|
+
|
193
|
+
def owned_by_this_machine?(name, machine_id)
|
194
|
+
labels = Util.read_network_labels(name)
|
195
|
+
labels["com.vagrant.plugin"] == "docker_networks_manager" &&
|
196
|
+
labels["com.vagrant.machine_id"] == machine_id
|
197
|
+
end
|
198
|
+
|
199
|
+
def delete_marker(env, name)
|
200
|
+
m = marker_path(env, name)
|
201
|
+
File.delete(m) if File.exist?(m)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|