Class: VagrantDockerNetworksManager::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant-docker-networks-manager/config.rb

Overview

Vagrant configuration for Docker network creation and cleanup.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfig

Returns a new instance of Config.



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/vagrant-docker-networks-manager/config.rb', line 26

def initialize
  @network_name       = UNSET_VALUE
  @network_subnet     = UNSET_VALUE
  @network_type       = UNSET_VALUE
  @network_gateway    = UNSET_VALUE
  @network_parent     = UNSET_VALUE
  @network_attachable = UNSET_VALUE
  @enable_ipv6        = UNSET_VALUE
  @ip_range           = UNSET_VALUE
  @cleanup_on_destroy = UNSET_VALUE
  @locale             = UNSET_VALUE
end

Instance Attribute Details

#cleanup_on_destroyBoolean

Returns Whether to remove the network during vagrant destroy.

Returns:

  • (Boolean)

    Whether to remove the network during vagrant destroy.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/vagrant-docker-networks-manager/config.rb', line 21

class Config < Vagrant.plugin("2", :config)
  attr_accessor :network_name, :network_subnet, :network_type, :network_gateway,
                :network_parent, :network_attachable, :enable_ipv6, :ip_range,
                :cleanup_on_destroy, :locale

  def initialize
    @network_name       = UNSET_VALUE
    @network_subnet     = UNSET_VALUE
    @network_type       = UNSET_VALUE
    @network_gateway    = UNSET_VALUE
    @network_parent     = UNSET_VALUE
    @network_attachable = UNSET_VALUE
    @enable_ipv6        = UNSET_VALUE
    @ip_range           = UNSET_VALUE
    @cleanup_on_destroy = UNSET_VALUE
    @locale             = UNSET_VALUE
  end

  def finalize!
    @network_name       = "network_lo1"       if @network_name       == UNSET_VALUE
    @network_subnet     = "172.28.100.0/26"   if @network_subnet     == UNSET_VALUE
    @network_type       = "bridge"            if @network_type       == UNSET_VALUE
    @network_gateway    = "172.28.100.1"      if @network_gateway    == UNSET_VALUE
    @network_parent     = nil                 if @network_parent     == UNSET_VALUE
    @network_attachable = false               if @network_attachable == UNSET_VALUE
    @enable_ipv6        = false               if @enable_ipv6        == UNSET_VALUE
    @ip_range           = nil                 if @ip_range           == UNSET_VALUE
    @cleanup_on_destroy = true                if @cleanup_on_destroy == UNSET_VALUE
    @locale             = "en"                if @locale             == UNSET_VALUE
  end

  def validate(_machine)
    setup_i18n_safely

    keys = [
      name_error, subnet_error, type_error, gateway_error, parent_error,
      attachable_error, ipv6_error, ip_range_error, cleanup_error, locale_error
    ].compact

    { "vagrant-docker-networks-manager" => keys.map { |key| UiHelpers.t(key) } }
  end

  private

  def setup_i18n_safely
    VagrantDockerNetworksManager::UiHelpers.setup_i18n!
  rescue StandardError
    nil
  end

  def name_error
    return if @network_name.is_a?(String) && !@network_name.strip.empty? && docker_name?(@network_name)

    "errors.invalid_name"
  end

  def subnet_error
    "errors.invalid_subnet" unless ipv4_cidr_aligned?(@network_subnet)
  end

  def type_error
    "errors.invalid_type" unless @network_type.is_a?(String) && %w[bridge macvlan].include?(@network_type)
  end

  def gateway_error
    return unless present?(@network_gateway)
    return "errors.invalid_gateway" unless ipv4?(@network_gateway)
    return "errors.invalid_gateway" if ipv4_cidr_aligned?(@network_subnet) &&
                                       !gateway_host_addr?(@network_subnet, @network_gateway)

    nil
  end

  def parent_error
    return "errors.invalid_parent" if present?(@network_parent) && !@network_parent.is_a?(String)
    return "errors.invalid_parent" if @network_type.to_s == "macvlan" && !present?(@network_parent)

    nil
  end

  def attachable_error
    "errors.invalid_attachable" unless [true, false].include?(@network_attachable)
  end

  def ipv6_error
    "errors.invalid_ipv6" unless [true, false].include?(@enable_ipv6)
  end

  def ip_range_error
    return unless present?(@ip_range)
    return "errors.invalid_ip_range" unless ipv4_cidr?(@ip_range)
    return "errors.invalid_ip_range" if ipv4_cidr_aligned?(@network_subnet) &&
                                        !cidr_within_cidr?(@network_subnet, @ip_range)

    nil
  end

  def cleanup_error
    "errors.invalid_cleanup" unless [true, false].include?(@cleanup_on_destroy)
  end

  def locale_error
    return if @locale.is_a?(String) && %w[fr en].include?(@locale.to_s[0, 2].downcase)

    "errors.invalid_locale"
  end

  def present?(val)
    !val.nil? && !(val.respond_to?(:empty?) && val.empty?)
  end

  def ipv4?(str)
    ip = IPAddr.new(str) rescue nil
    ip&.ipv4? ? true : false
  end

  def ipv4_cidr?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    ip&.ipv4? ? true : false
  rescue
    false
  end

  def ipv4_cidr_aligned?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    return false unless ip&.ipv4?
    ip.mask(m).to_s == ip_str
  rescue
    false
  end

  def gateway_host_addr?(cidr, gw)
    net = IPAddr.new(cidr) rescue nil
    ip  = IPAddr.new(gw)   rescue nil
    return false unless net&.ipv4? && ip&.ipv4? && net.include?(ip)
    mask = cidr.split("/")[1].to_i
    network = IPAddr.new(net.to_range.first.to_s).mask(mask)
    broadcast = IPAddr.new(net.to_range.last.to_s)
    ip != network && ip != broadcast
  rescue
    false
  end

  def cidr_within_cidr?(outer, inner)
    outer_ip, outer_mask = outer.to_s.split("/", 2)
    inner_ip, inner_mask = inner.to_s.split("/", 2)
    return false unless outer_ip && inner_ip && outer_mask&.match?(/^\d+$/) && inner_mask&.match?(/^\d+$/)

    om = outer_mask.to_i
    im = inner_mask.to_i
    return false unless (0..32).include?(om) && (0..32).include?(im)
    return false unless om <= im

    outer_net = IPAddr.new(outer_ip).mask(om) rescue nil
    inner_as_outer = IPAddr.new(inner_ip).mask(om) rescue nil
    outer_net&.ipv4? && inner_as_outer&.ipv4? && (inner_as_outer.to_s == outer_net.to_s)
  rescue
    false
  end

  def docker_name?(s)
    s.is_a?(String) && s.match?(/\A[a-zA-Z0-9][a-zA-Z0-9_.-]{0,126}\z/)
  end
end

#enable_ipv6Object

Returns the value of attribute enable_ipv6.



22
23
24
# File 'lib/vagrant-docker-networks-manager/config.rb', line 22

def enable_ipv6
  @enable_ipv6
end

#ip_rangeObject

Returns the value of attribute ip_range.



22
23
24
# File 'lib/vagrant-docker-networks-manager/config.rb', line 22

def ip_range
  @ip_range
end

#localeObject

Returns the value of attribute locale.



22
23
24
# File 'lib/vagrant-docker-networks-manager/config.rb', line 22

def locale
  @locale
end

#network_attachableObject

Returns the value of attribute network_attachable.



22
23
24
# File 'lib/vagrant-docker-networks-manager/config.rb', line 22

def network_attachable
  @network_attachable
end

#network_gatewayString?

Returns Optional gateway IP address.

Returns:

  • (String, nil)

    Optional gateway IP address.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/vagrant-docker-networks-manager/config.rb', line 21

class Config < Vagrant.plugin("2", :config)
  attr_accessor :network_name, :network_subnet, :network_type, :network_gateway,
                :network_parent, :network_attachable, :enable_ipv6, :ip_range,
                :cleanup_on_destroy, :locale

  def initialize
    @network_name       = UNSET_VALUE
    @network_subnet     = UNSET_VALUE
    @network_type       = UNSET_VALUE
    @network_gateway    = UNSET_VALUE
    @network_parent     = UNSET_VALUE
    @network_attachable = UNSET_VALUE
    @enable_ipv6        = UNSET_VALUE
    @ip_range           = UNSET_VALUE
    @cleanup_on_destroy = UNSET_VALUE
    @locale             = UNSET_VALUE
  end

  def finalize!
    @network_name       = "network_lo1"       if @network_name       == UNSET_VALUE
    @network_subnet     = "172.28.100.0/26"   if @network_subnet     == UNSET_VALUE
    @network_type       = "bridge"            if @network_type       == UNSET_VALUE
    @network_gateway    = "172.28.100.1"      if @network_gateway    == UNSET_VALUE
    @network_parent     = nil                 if @network_parent     == UNSET_VALUE
    @network_attachable = false               if @network_attachable == UNSET_VALUE
    @enable_ipv6        = false               if @enable_ipv6        == UNSET_VALUE
    @ip_range           = nil                 if @ip_range           == UNSET_VALUE
    @cleanup_on_destroy = true                if @cleanup_on_destroy == UNSET_VALUE
    @locale             = "en"                if @locale             == UNSET_VALUE
  end

  def validate(_machine)
    setup_i18n_safely

    keys = [
      name_error, subnet_error, type_error, gateway_error, parent_error,
      attachable_error, ipv6_error, ip_range_error, cleanup_error, locale_error
    ].compact

    { "vagrant-docker-networks-manager" => keys.map { |key| UiHelpers.t(key) } }
  end

  private

  def setup_i18n_safely
    VagrantDockerNetworksManager::UiHelpers.setup_i18n!
  rescue StandardError
    nil
  end

  def name_error
    return if @network_name.is_a?(String) && !@network_name.strip.empty? && docker_name?(@network_name)

    "errors.invalid_name"
  end

  def subnet_error
    "errors.invalid_subnet" unless ipv4_cidr_aligned?(@network_subnet)
  end

  def type_error
    "errors.invalid_type" unless @network_type.is_a?(String) && %w[bridge macvlan].include?(@network_type)
  end

  def gateway_error
    return unless present?(@network_gateway)
    return "errors.invalid_gateway" unless ipv4?(@network_gateway)
    return "errors.invalid_gateway" if ipv4_cidr_aligned?(@network_subnet) &&
                                       !gateway_host_addr?(@network_subnet, @network_gateway)

    nil
  end

  def parent_error
    return "errors.invalid_parent" if present?(@network_parent) && !@network_parent.is_a?(String)
    return "errors.invalid_parent" if @network_type.to_s == "macvlan" && !present?(@network_parent)

    nil
  end

  def attachable_error
    "errors.invalid_attachable" unless [true, false].include?(@network_attachable)
  end

  def ipv6_error
    "errors.invalid_ipv6" unless [true, false].include?(@enable_ipv6)
  end

  def ip_range_error
    return unless present?(@ip_range)
    return "errors.invalid_ip_range" unless ipv4_cidr?(@ip_range)
    return "errors.invalid_ip_range" if ipv4_cidr_aligned?(@network_subnet) &&
                                        !cidr_within_cidr?(@network_subnet, @ip_range)

    nil
  end

  def cleanup_error
    "errors.invalid_cleanup" unless [true, false].include?(@cleanup_on_destroy)
  end

  def locale_error
    return if @locale.is_a?(String) && %w[fr en].include?(@locale.to_s[0, 2].downcase)

    "errors.invalid_locale"
  end

  def present?(val)
    !val.nil? && !(val.respond_to?(:empty?) && val.empty?)
  end

  def ipv4?(str)
    ip = IPAddr.new(str) rescue nil
    ip&.ipv4? ? true : false
  end

  def ipv4_cidr?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    ip&.ipv4? ? true : false
  rescue
    false
  end

  def ipv4_cidr_aligned?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    return false unless ip&.ipv4?
    ip.mask(m).to_s == ip_str
  rescue
    false
  end

  def gateway_host_addr?(cidr, gw)
    net = IPAddr.new(cidr) rescue nil
    ip  = IPAddr.new(gw)   rescue nil
    return false unless net&.ipv4? && ip&.ipv4? && net.include?(ip)
    mask = cidr.split("/")[1].to_i
    network = IPAddr.new(net.to_range.first.to_s).mask(mask)
    broadcast = IPAddr.new(net.to_range.last.to_s)
    ip != network && ip != broadcast
  rescue
    false
  end

  def cidr_within_cidr?(outer, inner)
    outer_ip, outer_mask = outer.to_s.split("/", 2)
    inner_ip, inner_mask = inner.to_s.split("/", 2)
    return false unless outer_ip && inner_ip && outer_mask&.match?(/^\d+$/) && inner_mask&.match?(/^\d+$/)

    om = outer_mask.to_i
    im = inner_mask.to_i
    return false unless (0..32).include?(om) && (0..32).include?(im)
    return false unless om <= im

    outer_net = IPAddr.new(outer_ip).mask(om) rescue nil
    inner_as_outer = IPAddr.new(inner_ip).mask(om) rescue nil
    outer_net&.ipv4? && inner_as_outer&.ipv4? && (inner_as_outer.to_s == outer_net.to_s)
  rescue
    false
  end

  def docker_name?(s)
    s.is_a?(String) && s.match?(/\A[a-zA-Z0-9][a-zA-Z0-9_.-]{0,126}\z/)
  end
end

#network_nameString

Returns Docker network name.

Returns:

  • (String)

    Docker network name.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/vagrant-docker-networks-manager/config.rb', line 21

class Config < Vagrant.plugin("2", :config)
  attr_accessor :network_name, :network_subnet, :network_type, :network_gateway,
                :network_parent, :network_attachable, :enable_ipv6, :ip_range,
                :cleanup_on_destroy, :locale

  def initialize
    @network_name       = UNSET_VALUE
    @network_subnet     = UNSET_VALUE
    @network_type       = UNSET_VALUE
    @network_gateway    = UNSET_VALUE
    @network_parent     = UNSET_VALUE
    @network_attachable = UNSET_VALUE
    @enable_ipv6        = UNSET_VALUE
    @ip_range           = UNSET_VALUE
    @cleanup_on_destroy = UNSET_VALUE
    @locale             = UNSET_VALUE
  end

  def finalize!
    @network_name       = "network_lo1"       if @network_name       == UNSET_VALUE
    @network_subnet     = "172.28.100.0/26"   if @network_subnet     == UNSET_VALUE
    @network_type       = "bridge"            if @network_type       == UNSET_VALUE
    @network_gateway    = "172.28.100.1"      if @network_gateway    == UNSET_VALUE
    @network_parent     = nil                 if @network_parent     == UNSET_VALUE
    @network_attachable = false               if @network_attachable == UNSET_VALUE
    @enable_ipv6        = false               if @enable_ipv6        == UNSET_VALUE
    @ip_range           = nil                 if @ip_range           == UNSET_VALUE
    @cleanup_on_destroy = true                if @cleanup_on_destroy == UNSET_VALUE
    @locale             = "en"                if @locale             == UNSET_VALUE
  end

  def validate(_machine)
    setup_i18n_safely

    keys = [
      name_error, subnet_error, type_error, gateway_error, parent_error,
      attachable_error, ipv6_error, ip_range_error, cleanup_error, locale_error
    ].compact

    { "vagrant-docker-networks-manager" => keys.map { |key| UiHelpers.t(key) } }
  end

  private

  def setup_i18n_safely
    VagrantDockerNetworksManager::UiHelpers.setup_i18n!
  rescue StandardError
    nil
  end

  def name_error
    return if @network_name.is_a?(String) && !@network_name.strip.empty? && docker_name?(@network_name)

    "errors.invalid_name"
  end

  def subnet_error
    "errors.invalid_subnet" unless ipv4_cidr_aligned?(@network_subnet)
  end

  def type_error
    "errors.invalid_type" unless @network_type.is_a?(String) && %w[bridge macvlan].include?(@network_type)
  end

  def gateway_error
    return unless present?(@network_gateway)
    return "errors.invalid_gateway" unless ipv4?(@network_gateway)
    return "errors.invalid_gateway" if ipv4_cidr_aligned?(@network_subnet) &&
                                       !gateway_host_addr?(@network_subnet, @network_gateway)

    nil
  end

  def parent_error
    return "errors.invalid_parent" if present?(@network_parent) && !@network_parent.is_a?(String)
    return "errors.invalid_parent" if @network_type.to_s == "macvlan" && !present?(@network_parent)

    nil
  end

  def attachable_error
    "errors.invalid_attachable" unless [true, false].include?(@network_attachable)
  end

  def ipv6_error
    "errors.invalid_ipv6" unless [true, false].include?(@enable_ipv6)
  end

  def ip_range_error
    return unless present?(@ip_range)
    return "errors.invalid_ip_range" unless ipv4_cidr?(@ip_range)
    return "errors.invalid_ip_range" if ipv4_cidr_aligned?(@network_subnet) &&
                                        !cidr_within_cidr?(@network_subnet, @ip_range)

    nil
  end

  def cleanup_error
    "errors.invalid_cleanup" unless [true, false].include?(@cleanup_on_destroy)
  end

  def locale_error
    return if @locale.is_a?(String) && %w[fr en].include?(@locale.to_s[0, 2].downcase)

    "errors.invalid_locale"
  end

  def present?(val)
    !val.nil? && !(val.respond_to?(:empty?) && val.empty?)
  end

  def ipv4?(str)
    ip = IPAddr.new(str) rescue nil
    ip&.ipv4? ? true : false
  end

  def ipv4_cidr?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    ip&.ipv4? ? true : false
  rescue
    false
  end

  def ipv4_cidr_aligned?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    return false unless ip&.ipv4?
    ip.mask(m).to_s == ip_str
  rescue
    false
  end

  def gateway_host_addr?(cidr, gw)
    net = IPAddr.new(cidr) rescue nil
    ip  = IPAddr.new(gw)   rescue nil
    return false unless net&.ipv4? && ip&.ipv4? && net.include?(ip)
    mask = cidr.split("/")[1].to_i
    network = IPAddr.new(net.to_range.first.to_s).mask(mask)
    broadcast = IPAddr.new(net.to_range.last.to_s)
    ip != network && ip != broadcast
  rescue
    false
  end

  def cidr_within_cidr?(outer, inner)
    outer_ip, outer_mask = outer.to_s.split("/", 2)
    inner_ip, inner_mask = inner.to_s.split("/", 2)
    return false unless outer_ip && inner_ip && outer_mask&.match?(/^\d+$/) && inner_mask&.match?(/^\d+$/)

    om = outer_mask.to_i
    im = inner_mask.to_i
    return false unless (0..32).include?(om) && (0..32).include?(im)
    return false unless om <= im

    outer_net = IPAddr.new(outer_ip).mask(om) rescue nil
    inner_as_outer = IPAddr.new(inner_ip).mask(om) rescue nil
    outer_net&.ipv4? && inner_as_outer&.ipv4? && (inner_as_outer.to_s == outer_net.to_s)
  rescue
    false
  end

  def docker_name?(s)
    s.is_a?(String) && s.match?(/\A[a-zA-Z0-9][a-zA-Z0-9_.-]{0,126}\z/)
  end
end

#network_parentString?

Returns Parent interface for macvlan networks.

Returns:

  • (String, nil)

    Parent interface for macvlan networks.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/vagrant-docker-networks-manager/config.rb', line 21

class Config < Vagrant.plugin("2", :config)
  attr_accessor :network_name, :network_subnet, :network_type, :network_gateway,
                :network_parent, :network_attachable, :enable_ipv6, :ip_range,
                :cleanup_on_destroy, :locale

  def initialize
    @network_name       = UNSET_VALUE
    @network_subnet     = UNSET_VALUE
    @network_type       = UNSET_VALUE
    @network_gateway    = UNSET_VALUE
    @network_parent     = UNSET_VALUE
    @network_attachable = UNSET_VALUE
    @enable_ipv6        = UNSET_VALUE
    @ip_range           = UNSET_VALUE
    @cleanup_on_destroy = UNSET_VALUE
    @locale             = UNSET_VALUE
  end

  def finalize!
    @network_name       = "network_lo1"       if @network_name       == UNSET_VALUE
    @network_subnet     = "172.28.100.0/26"   if @network_subnet     == UNSET_VALUE
    @network_type       = "bridge"            if @network_type       == UNSET_VALUE
    @network_gateway    = "172.28.100.1"      if @network_gateway    == UNSET_VALUE
    @network_parent     = nil                 if @network_parent     == UNSET_VALUE
    @network_attachable = false               if @network_attachable == UNSET_VALUE
    @enable_ipv6        = false               if @enable_ipv6        == UNSET_VALUE
    @ip_range           = nil                 if @ip_range           == UNSET_VALUE
    @cleanup_on_destroy = true                if @cleanup_on_destroy == UNSET_VALUE
    @locale             = "en"                if @locale             == UNSET_VALUE
  end

  def validate(_machine)
    setup_i18n_safely

    keys = [
      name_error, subnet_error, type_error, gateway_error, parent_error,
      attachable_error, ipv6_error, ip_range_error, cleanup_error, locale_error
    ].compact

    { "vagrant-docker-networks-manager" => keys.map { |key| UiHelpers.t(key) } }
  end

  private

  def setup_i18n_safely
    VagrantDockerNetworksManager::UiHelpers.setup_i18n!
  rescue StandardError
    nil
  end

  def name_error
    return if @network_name.is_a?(String) && !@network_name.strip.empty? && docker_name?(@network_name)

    "errors.invalid_name"
  end

  def subnet_error
    "errors.invalid_subnet" unless ipv4_cidr_aligned?(@network_subnet)
  end

  def type_error
    "errors.invalid_type" unless @network_type.is_a?(String) && %w[bridge macvlan].include?(@network_type)
  end

  def gateway_error
    return unless present?(@network_gateway)
    return "errors.invalid_gateway" unless ipv4?(@network_gateway)
    return "errors.invalid_gateway" if ipv4_cidr_aligned?(@network_subnet) &&
                                       !gateway_host_addr?(@network_subnet, @network_gateway)

    nil
  end

  def parent_error
    return "errors.invalid_parent" if present?(@network_parent) && !@network_parent.is_a?(String)
    return "errors.invalid_parent" if @network_type.to_s == "macvlan" && !present?(@network_parent)

    nil
  end

  def attachable_error
    "errors.invalid_attachable" unless [true, false].include?(@network_attachable)
  end

  def ipv6_error
    "errors.invalid_ipv6" unless [true, false].include?(@enable_ipv6)
  end

  def ip_range_error
    return unless present?(@ip_range)
    return "errors.invalid_ip_range" unless ipv4_cidr?(@ip_range)
    return "errors.invalid_ip_range" if ipv4_cidr_aligned?(@network_subnet) &&
                                        !cidr_within_cidr?(@network_subnet, @ip_range)

    nil
  end

  def cleanup_error
    "errors.invalid_cleanup" unless [true, false].include?(@cleanup_on_destroy)
  end

  def locale_error
    return if @locale.is_a?(String) && %w[fr en].include?(@locale.to_s[0, 2].downcase)

    "errors.invalid_locale"
  end

  def present?(val)
    !val.nil? && !(val.respond_to?(:empty?) && val.empty?)
  end

  def ipv4?(str)
    ip = IPAddr.new(str) rescue nil
    ip&.ipv4? ? true : false
  end

  def ipv4_cidr?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    ip&.ipv4? ? true : false
  rescue
    false
  end

  def ipv4_cidr_aligned?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    return false unless ip&.ipv4?
    ip.mask(m).to_s == ip_str
  rescue
    false
  end

  def gateway_host_addr?(cidr, gw)
    net = IPAddr.new(cidr) rescue nil
    ip  = IPAddr.new(gw)   rescue nil
    return false unless net&.ipv4? && ip&.ipv4? && net.include?(ip)
    mask = cidr.split("/")[1].to_i
    network = IPAddr.new(net.to_range.first.to_s).mask(mask)
    broadcast = IPAddr.new(net.to_range.last.to_s)
    ip != network && ip != broadcast
  rescue
    false
  end

  def cidr_within_cidr?(outer, inner)
    outer_ip, outer_mask = outer.to_s.split("/", 2)
    inner_ip, inner_mask = inner.to_s.split("/", 2)
    return false unless outer_ip && inner_ip && outer_mask&.match?(/^\d+$/) && inner_mask&.match?(/^\d+$/)

    om = outer_mask.to_i
    im = inner_mask.to_i
    return false unless (0..32).include?(om) && (0..32).include?(im)
    return false unless om <= im

    outer_net = IPAddr.new(outer_ip).mask(om) rescue nil
    inner_as_outer = IPAddr.new(inner_ip).mask(om) rescue nil
    outer_net&.ipv4? && inner_as_outer&.ipv4? && (inner_as_outer.to_s == outer_net.to_s)
  rescue
    false
  end

  def docker_name?(s)
    s.is_a?(String) && s.match?(/\A[a-zA-Z0-9][a-zA-Z0-9_.-]{0,126}\z/)
  end
end

#network_subnetString

Returns IPv4 subnet in CIDR notation.

Returns:

  • (String)

    IPv4 subnet in CIDR notation.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/vagrant-docker-networks-manager/config.rb', line 21

class Config < Vagrant.plugin("2", :config)
  attr_accessor :network_name, :network_subnet, :network_type, :network_gateway,
                :network_parent, :network_attachable, :enable_ipv6, :ip_range,
                :cleanup_on_destroy, :locale

  def initialize
    @network_name       = UNSET_VALUE
    @network_subnet     = UNSET_VALUE
    @network_type       = UNSET_VALUE
    @network_gateway    = UNSET_VALUE
    @network_parent     = UNSET_VALUE
    @network_attachable = UNSET_VALUE
    @enable_ipv6        = UNSET_VALUE
    @ip_range           = UNSET_VALUE
    @cleanup_on_destroy = UNSET_VALUE
    @locale             = UNSET_VALUE
  end

  def finalize!
    @network_name       = "network_lo1"       if @network_name       == UNSET_VALUE
    @network_subnet     = "172.28.100.0/26"   if @network_subnet     == UNSET_VALUE
    @network_type       = "bridge"            if @network_type       == UNSET_VALUE
    @network_gateway    = "172.28.100.1"      if @network_gateway    == UNSET_VALUE
    @network_parent     = nil                 if @network_parent     == UNSET_VALUE
    @network_attachable = false               if @network_attachable == UNSET_VALUE
    @enable_ipv6        = false               if @enable_ipv6        == UNSET_VALUE
    @ip_range           = nil                 if @ip_range           == UNSET_VALUE
    @cleanup_on_destroy = true                if @cleanup_on_destroy == UNSET_VALUE
    @locale             = "en"                if @locale             == UNSET_VALUE
  end

  def validate(_machine)
    setup_i18n_safely

    keys = [
      name_error, subnet_error, type_error, gateway_error, parent_error,
      attachable_error, ipv6_error, ip_range_error, cleanup_error, locale_error
    ].compact

    { "vagrant-docker-networks-manager" => keys.map { |key| UiHelpers.t(key) } }
  end

  private

  def setup_i18n_safely
    VagrantDockerNetworksManager::UiHelpers.setup_i18n!
  rescue StandardError
    nil
  end

  def name_error
    return if @network_name.is_a?(String) && !@network_name.strip.empty? && docker_name?(@network_name)

    "errors.invalid_name"
  end

  def subnet_error
    "errors.invalid_subnet" unless ipv4_cidr_aligned?(@network_subnet)
  end

  def type_error
    "errors.invalid_type" unless @network_type.is_a?(String) && %w[bridge macvlan].include?(@network_type)
  end

  def gateway_error
    return unless present?(@network_gateway)
    return "errors.invalid_gateway" unless ipv4?(@network_gateway)
    return "errors.invalid_gateway" if ipv4_cidr_aligned?(@network_subnet) &&
                                       !gateway_host_addr?(@network_subnet, @network_gateway)

    nil
  end

  def parent_error
    return "errors.invalid_parent" if present?(@network_parent) && !@network_parent.is_a?(String)
    return "errors.invalid_parent" if @network_type.to_s == "macvlan" && !present?(@network_parent)

    nil
  end

  def attachable_error
    "errors.invalid_attachable" unless [true, false].include?(@network_attachable)
  end

  def ipv6_error
    "errors.invalid_ipv6" unless [true, false].include?(@enable_ipv6)
  end

  def ip_range_error
    return unless present?(@ip_range)
    return "errors.invalid_ip_range" unless ipv4_cidr?(@ip_range)
    return "errors.invalid_ip_range" if ipv4_cidr_aligned?(@network_subnet) &&
                                        !cidr_within_cidr?(@network_subnet, @ip_range)

    nil
  end

  def cleanup_error
    "errors.invalid_cleanup" unless [true, false].include?(@cleanup_on_destroy)
  end

  def locale_error
    return if @locale.is_a?(String) && %w[fr en].include?(@locale.to_s[0, 2].downcase)

    "errors.invalid_locale"
  end

  def present?(val)
    !val.nil? && !(val.respond_to?(:empty?) && val.empty?)
  end

  def ipv4?(str)
    ip = IPAddr.new(str) rescue nil
    ip&.ipv4? ? true : false
  end

  def ipv4_cidr?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    ip&.ipv4? ? true : false
  rescue
    false
  end

  def ipv4_cidr_aligned?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    return false unless ip&.ipv4?
    ip.mask(m).to_s == ip_str
  rescue
    false
  end

  def gateway_host_addr?(cidr, gw)
    net = IPAddr.new(cidr) rescue nil
    ip  = IPAddr.new(gw)   rescue nil
    return false unless net&.ipv4? && ip&.ipv4? && net.include?(ip)
    mask = cidr.split("/")[1].to_i
    network = IPAddr.new(net.to_range.first.to_s).mask(mask)
    broadcast = IPAddr.new(net.to_range.last.to_s)
    ip != network && ip != broadcast
  rescue
    false
  end

  def cidr_within_cidr?(outer, inner)
    outer_ip, outer_mask = outer.to_s.split("/", 2)
    inner_ip, inner_mask = inner.to_s.split("/", 2)
    return false unless outer_ip && inner_ip && outer_mask&.match?(/^\d+$/) && inner_mask&.match?(/^\d+$/)

    om = outer_mask.to_i
    im = inner_mask.to_i
    return false unless (0..32).include?(om) && (0..32).include?(im)
    return false unless om <= im

    outer_net = IPAddr.new(outer_ip).mask(om) rescue nil
    inner_as_outer = IPAddr.new(inner_ip).mask(om) rescue nil
    outer_net&.ipv4? && inner_as_outer&.ipv4? && (inner_as_outer.to_s == outer_net.to_s)
  rescue
    false
  end

  def docker_name?(s)
    s.is_a?(String) && s.match?(/\A[a-zA-Z0-9][a-zA-Z0-9_.-]{0,126}\z/)
  end
end

#network_typeString

Returns Docker network driver.

Returns:

  • (String)

    Docker network driver.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/vagrant-docker-networks-manager/config.rb', line 21

class Config < Vagrant.plugin("2", :config)
  attr_accessor :network_name, :network_subnet, :network_type, :network_gateway,
                :network_parent, :network_attachable, :enable_ipv6, :ip_range,
                :cleanup_on_destroy, :locale

  def initialize
    @network_name       = UNSET_VALUE
    @network_subnet     = UNSET_VALUE
    @network_type       = UNSET_VALUE
    @network_gateway    = UNSET_VALUE
    @network_parent     = UNSET_VALUE
    @network_attachable = UNSET_VALUE
    @enable_ipv6        = UNSET_VALUE
    @ip_range           = UNSET_VALUE
    @cleanup_on_destroy = UNSET_VALUE
    @locale             = UNSET_VALUE
  end

  def finalize!
    @network_name       = "network_lo1"       if @network_name       == UNSET_VALUE
    @network_subnet     = "172.28.100.0/26"   if @network_subnet     == UNSET_VALUE
    @network_type       = "bridge"            if @network_type       == UNSET_VALUE
    @network_gateway    = "172.28.100.1"      if @network_gateway    == UNSET_VALUE
    @network_parent     = nil                 if @network_parent     == UNSET_VALUE
    @network_attachable = false               if @network_attachable == UNSET_VALUE
    @enable_ipv6        = false               if @enable_ipv6        == UNSET_VALUE
    @ip_range           = nil                 if @ip_range           == UNSET_VALUE
    @cleanup_on_destroy = true                if @cleanup_on_destroy == UNSET_VALUE
    @locale             = "en"                if @locale             == UNSET_VALUE
  end

  def validate(_machine)
    setup_i18n_safely

    keys = [
      name_error, subnet_error, type_error, gateway_error, parent_error,
      attachable_error, ipv6_error, ip_range_error, cleanup_error, locale_error
    ].compact

    { "vagrant-docker-networks-manager" => keys.map { |key| UiHelpers.t(key) } }
  end

  private

  def setup_i18n_safely
    VagrantDockerNetworksManager::UiHelpers.setup_i18n!
  rescue StandardError
    nil
  end

  def name_error
    return if @network_name.is_a?(String) && !@network_name.strip.empty? && docker_name?(@network_name)

    "errors.invalid_name"
  end

  def subnet_error
    "errors.invalid_subnet" unless ipv4_cidr_aligned?(@network_subnet)
  end

  def type_error
    "errors.invalid_type" unless @network_type.is_a?(String) && %w[bridge macvlan].include?(@network_type)
  end

  def gateway_error
    return unless present?(@network_gateway)
    return "errors.invalid_gateway" unless ipv4?(@network_gateway)
    return "errors.invalid_gateway" if ipv4_cidr_aligned?(@network_subnet) &&
                                       !gateway_host_addr?(@network_subnet, @network_gateway)

    nil
  end

  def parent_error
    return "errors.invalid_parent" if present?(@network_parent) && !@network_parent.is_a?(String)
    return "errors.invalid_parent" if @network_type.to_s == "macvlan" && !present?(@network_parent)

    nil
  end

  def attachable_error
    "errors.invalid_attachable" unless [true, false].include?(@network_attachable)
  end

  def ipv6_error
    "errors.invalid_ipv6" unless [true, false].include?(@enable_ipv6)
  end

  def ip_range_error
    return unless present?(@ip_range)
    return "errors.invalid_ip_range" unless ipv4_cidr?(@ip_range)
    return "errors.invalid_ip_range" if ipv4_cidr_aligned?(@network_subnet) &&
                                        !cidr_within_cidr?(@network_subnet, @ip_range)

    nil
  end

  def cleanup_error
    "errors.invalid_cleanup" unless [true, false].include?(@cleanup_on_destroy)
  end

  def locale_error
    return if @locale.is_a?(String) && %w[fr en].include?(@locale.to_s[0, 2].downcase)

    "errors.invalid_locale"
  end

  def present?(val)
    !val.nil? && !(val.respond_to?(:empty?) && val.empty?)
  end

  def ipv4?(str)
    ip = IPAddr.new(str) rescue nil
    ip&.ipv4? ? true : false
  end

  def ipv4_cidr?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    ip&.ipv4? ? true : false
  rescue
    false
  end

  def ipv4_cidr_aligned?(str)
    ip_str, mask_str = str.to_s.split("/", 2)
    return false unless ip_str && mask_str&.match?(/^\d+$/)
    m = mask_str.to_i
    return false unless (0..32).include?(m)
    ip = IPAddr.new(ip_str) rescue nil
    return false unless ip&.ipv4?
    ip.mask(m).to_s == ip_str
  rescue
    false
  end

  def gateway_host_addr?(cidr, gw)
    net = IPAddr.new(cidr) rescue nil
    ip  = IPAddr.new(gw)   rescue nil
    return false unless net&.ipv4? && ip&.ipv4? && net.include?(ip)
    mask = cidr.split("/")[1].to_i
    network = IPAddr.new(net.to_range.first.to_s).mask(mask)
    broadcast = IPAddr.new(net.to_range.last.to_s)
    ip != network && ip != broadcast
  rescue
    false
  end

  def cidr_within_cidr?(outer, inner)
    outer_ip, outer_mask = outer.to_s.split("/", 2)
    inner_ip, inner_mask = inner.to_s.split("/", 2)
    return false unless outer_ip && inner_ip && outer_mask&.match?(/^\d+$/) && inner_mask&.match?(/^\d+$/)

    om = outer_mask.to_i
    im = inner_mask.to_i
    return false unless (0..32).include?(om) && (0..32).include?(im)
    return false unless om <= im

    outer_net = IPAddr.new(outer_ip).mask(om) rescue nil
    inner_as_outer = IPAddr.new(inner_ip).mask(om) rescue nil
    outer_net&.ipv4? && inner_as_outer&.ipv4? && (inner_as_outer.to_s == outer_net.to_s)
  rescue
    false
  end

  def docker_name?(s)
    s.is_a?(String) && s.match?(/\A[a-zA-Z0-9][a-zA-Z0-9_.-]{0,126}\z/)
  end
end

Instance Method Details

#finalize!Object



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/vagrant-docker-networks-manager/config.rb', line 39

def finalize!
  @network_name       = "network_lo1"       if @network_name       == UNSET_VALUE
  @network_subnet     = "172.28.100.0/26"   if @network_subnet     == UNSET_VALUE
  @network_type       = "bridge"            if @network_type       == UNSET_VALUE
  @network_gateway    = "172.28.100.1"      if @network_gateway    == UNSET_VALUE
  @network_parent     = nil                 if @network_parent     == UNSET_VALUE
  @network_attachable = false               if @network_attachable == UNSET_VALUE
  @enable_ipv6        = false               if @enable_ipv6        == UNSET_VALUE
  @ip_range           = nil                 if @ip_range           == UNSET_VALUE
  @cleanup_on_destroy = true                if @cleanup_on_destroy == UNSET_VALUE
  @locale             = "en"                if @locale             == UNSET_VALUE
end

#validate(_machine) ⇒ Object



52
53
54
55
56
57
58
59
60
61
# File 'lib/vagrant-docker-networks-manager/config.rb', line 52

def validate(_machine)
  setup_i18n_safely

  keys = [
    name_error, subnet_error, type_error, gateway_error, parent_error,
    attachable_error, ipv6_error, ip_range_error, cleanup_error, locale_error
  ].compact

  { "vagrant-docker-networks-manager" => keys.map { |key| UiHelpers.t(key) } }
end