Update how docker network provider creates networks

This commit updates the docker network provider to only create networks
by subnet rather than per-container.
This commit is contained in:
Brian Cain 2019-03-01 16:07:53 -08:00
parent c20de9044d
commit 000457a012
No known key found for this signature in database
GPG Key ID: 9FC4639B2E4510A0
3 changed files with 32 additions and 50 deletions

View File

@ -21,9 +21,11 @@ module VagrantPlugins
# We only handle private and public networks # We only handle private and public networks
next if type != :private_network && type != :public_network next if type != :private_network && type != :public_network
# If network is defined in machines config as isolated single container network, then delete if options[:subnet]
# If it's custom and or default, check if other containers are using it, and if not, delete network_name = "vagrant_network_#{options[:subnet]}"
network_name = "#{env[:root_path].basename.to_s}_network_#{machine.name}" else
network_name = "vagrant_network"
end
if machine.provider.driver.existing_network?(network_name) && if machine.provider.driver.existing_network?(network_name) &&
!machine.provider.driver.network_used?(network_name) !machine.provider.driver.network_used?(network_name)

View File

@ -9,51 +9,20 @@ module VagrantPlugins
@logger = Log4r::Logger.new('vagrant::plugins::docker::network') @logger = Log4r::Logger.new('vagrant::plugins::docker::network')
end end
# TODO: This is not ideal, but not enitrely sure a good way
# around this without either having separate config options (which is worse for the user)
# or forcing them to care about options for each separate docker network command (which is also
# not great for the user). Basically a user wants to say:
#
# config.vm.network :private_network, <config options>
#
# We could limit the options to be name spaced simply `docker__option` like
#
# config.vm.network :private_network, docker__ip: "ip here"
#
# But then we will need this method to split out each option for creating and connecting networks
#
# Alternatively we could do
#
# - `docker__create__option`
# - `docker__connect__option`
# - ...etc...
#
# config.vm.network :private_network, docker__connect__ip: "ip here",
# docker__create__subnet: "subnet"
#
# But this will force users to care about what options are for which commands,
# but maybe they will have to care about it anyway, and it isn't that big of
# a deal for the extra namespacing?
#
# Extra namespacing puts more effort on the user side, but would allow us
# to be 'smarter' about how we set options in code by seeing essnetially
# what command the flag/option is intended for, rather than us trying to keep
# track of the commands/flags manually in this function.
#
# @param[Hash] options - options from the network config # @param[Hash] options - options from the network config
# @returns[Hash] cli_opts - an array of strings used for the network commnad # @returns[Array] cli_opts - an array of strings used for the network commnad
def parse_cli_arguments(options) def parse_cli_arguments(options)
cli_opts = {create: [], connect: []} cli_opts = []
# Splits the networking options to generate the proper CLI flags for docker # Splits the networking options to generate the proper CLI flags for docker
if options[:type] != "dhcp" options.each do |opt, value|
options.each do |opt, value| opt = opt.to_s
vals = opt.to_s.split("__") if opt == "ip" || (opt == "type" && value = "dhcp") ||
if vals[0] == "docker" && vals.size == 3 opt == "protocol" || opt == "id"
cli_opts[vals[1].to_sym].concat(["--#{vals[2]}", value]) # `docker network create` doesn't care about these options
else next
@logger.debug("Unsupported network option encountered: #{opt}. Ignoring...") else
end cli_opts.concat(["--#{opt}", value])
end end
end end
@ -76,18 +45,29 @@ module VagrantPlugins
cli_opts = parse_cli_arguments(options) cli_opts = parse_cli_arguments(options)
network_name = "#{env[:root_path].basename.to_s}_network_#{machine.name}" if options[:subnet]
network_name = "vagrant_network_#{options[:subnet]}"
elsif options[:type] == "dhcp"
network_name = "vagrant_network"
else
# TODO: Make this an error class
raise "Must specify a `subnet` or use `dhcp`"
end
container_id = machine.id container_id = machine.id
if !machine.provider.driver.existing_network?(network_name) if !machine.provider.driver.existing_network?(network_name)
@logger.debug("Creating network #{network_name}") @logger.debug("Creating network #{network_name}")
machine.provider.driver.create_network(network_name, cli_opts[:create]) machine.provider.driver.create_network(network_name, cli_opts)
else else
@logger.debug("Network #{network_name} already created") @logger.debug("Network #{network_name} already created")
end end
@logger.debug("Connecting network #{network_name} to container guest #{machine.name}") @logger.debug("Connecting network #{network_name} to container guest #{machine.name}")
machine.provider.driver.connect_network(network_name, container_id, cli_opts[:connect]) connect_opts = []
if options[:ip]
connect_opts = ["--ip", options[:ip]]
end
machine.provider.driver.connect_network(network_name, container_id, connect_opts)
end end
@app.call(env) @app.call(env)

View File

@ -246,15 +246,15 @@ module VagrantPlugins
# Docker network helpers # Docker network helpers
# ###################### # ######################
# Looks to see if a docker network has already been defined
#
# @param [String] network - name of network to look for # @param [String] network - name of network to look for
def existing_network?(network) def existing_network?(network)
result = list_network(["--format='{{json .Name}}'"]) result = list_network(["--format='{{json .Name}}'"])
#TODO: we should be more explicit here if we can #TODO: we should be more explicit here if we can
result.include?(network) result.match?(/\"#{network}\"/)
end end
# Looks to see if a docker network has already been defined
#
# @param [String] network - name of network to look for # @param [String] network - name of network to look for
# @return [Bool] # @return [Bool]
def network_used?(network) def network_used?(network)