From 78f9905dc66b4ea4f3e140cc581a136b6def1d56 Mon Sep 17 00:00:00 2001 From: AntonioCS Date: Fri, 26 Dec 2025 11:31:37 +0000 Subject: [PATCH] Add docker network management targets (v2.2.5) - docker/network/create/ - Create network (fails if exists) - docker/network/ensure/ - Create if missing (idempotent) - docker/network/remove/ - Remove network (fails if not exists) Features: - Flexible config via target params or variables - Format: [@driver][@subnet][@gateway] - Variables: docker_network__driver/subnet/gateway - docker_network_ignore_errors to suppress errors silently - dk_network_default_driver config (default: bridge) Functions added: - dk_network_parse_params - Parse target parameters - dk_network_create - Create network with options - dk_network_remove - Remove network Tests: 9 new tests covering all functions --- CHANGELOG.md | 14 +++ modules/containers/docker/docker_test.mk | 109 +++++++++++++++++++++++ modules/containers/docker/functions.mk | 77 ++++++++++++++++ modules/containers/docker/mod_config.mk | 8 +- modules/containers/docker/targets.mk | 72 +++++++++++++++ 5 files changed, 278 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aa6f8b..b134a3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## [2.2.5] - 2025-12-26 + +### Added +- **Docker module**: Network management targets + - `docker/network/create/` - Create a network (fails if exists) + - `docker/network/ensure/` - Create network if it doesn't exist (idempotent) + - `docker/network/remove/` - Remove a network (fails if doesn't exist) + - Flexible configuration via target parameters or variables: + - Target format: `[@driver][@subnet][@gateway]` + - Variable format: `docker_network__driver`, `docker_network__subnet`, `docker_network__gateway` + - `docker_network_ignore_errors` variable to suppress errors silently + - `dk_network_default_driver` config (default: bridge) + - Helper functions: `dk_network_parse_params`, `dk_network_create`, `dk_network_remove` + ## [2.2.4] - 2025-12-15 ### Added diff --git a/modules/containers/docker/docker_test.mk b/modules/containers/docker/docker_test.mk index 1b27396..eaf5639 100644 --- a/modules/containers/docker/docker_test.mk +++ b/modules/containers/docker/docker_test.mk @@ -137,4 +137,113 @@ define test_modules_docker_config_defaults $(call mb_assert_eq,/bin/sh,$(dk_shell_default),dk_shell_default should be /bin/sh) $(call mb_assert_eq,-it,$(dk_exec_default_tty),dk_exec_default_tty should be -it) $(call mb_assert_eq,--tail=200,$(dk_logs_default_opts),dk_logs_default_opts should be --tail=200) + $(call mb_assert_eq,bridge,$(dk_network_default_driver),dk_network_default_driver should be bridge) +endef + +###################################################################################### +# dk_network_parse_params tests +###################################################################################### + +define test_modules_docker_dk_network_parse_params_name_only + ## Test with name only (no @) + $(call dk_network_parse_params,mynetwork) + $(call mb_assert_eq,mynetwork,$(dk_network_parse_params_name),name should be mynetwork) + $(call mb_assert_eq,bridge,$(dk_network_parse_params_driver),driver should default to bridge) + $(call mb_assert_empty,$(dk_network_parse_params_subnet),subnet should be empty) + $(call mb_assert_empty,$(dk_network_parse_params_gateway),gateway should be empty) +endef + +define test_modules_docker_dk_network_parse_params_with_driver + ## Test with name and driver + $(call dk_network_parse_params,mynetwork@overlay) + $(call mb_assert_eq,mynetwork,$(dk_network_parse_params_name),name should be mynetwork) + $(call mb_assert_eq,overlay,$(dk_network_parse_params_driver),driver should be overlay) + $(call mb_assert_empty,$(dk_network_parse_params_subnet),subnet should be empty) + $(call mb_assert_empty,$(dk_network_parse_params_gateway),gateway should be empty) +endef + +define test_modules_docker_dk_network_parse_params_full + ## Test with all parameters + $(call dk_network_parse_params,mynetwork@bridge@172.20.0.0/16@172.20.0.1) + $(call mb_assert_eq,mynetwork,$(dk_network_parse_params_name),name should be mynetwork) + $(call mb_assert_eq,bridge,$(dk_network_parse_params_driver),driver should be bridge) + $(call mb_assert_eq,172.20.0.0/16,$(dk_network_parse_params_subnet),subnet should be 172.20.0.0/16) + $(call mb_assert_eq,172.20.0.1,$(dk_network_parse_params_gateway),gateway should be 172.20.0.1) +endef + +define test_modules_docker_dk_network_parse_params_from_variables + ## Test resolution from variables when no target params + $(eval docker_network_testnet_driver := overlay) + $(eval docker_network_testnet_subnet := 10.0.0.0/24) + $(eval docker_network_testnet_gateway := 10.0.0.1) + + $(call dk_network_parse_params,testnet) + $(call mb_assert_eq,testnet,$(dk_network_parse_params_name),name should be testnet) + $(call mb_assert_eq,overlay,$(dk_network_parse_params_driver),driver should come from variable) + $(call mb_assert_eq,10.0.0.0/24,$(dk_network_parse_params_subnet),subnet should come from variable) + $(call mb_assert_eq,10.0.0.1,$(dk_network_parse_params_gateway),gateway should come from variable) + + ## Cleanup + $(eval docker_network_testnet_driver :=) + $(eval docker_network_testnet_subnet :=) + $(eval docker_network_testnet_gateway :=) +endef + +define test_modules_docker_dk_network_parse_params_target_overrides_variable + ## Test that target params override variables + $(eval docker_network_mynet_driver := host) + $(eval docker_network_mynet_subnet := 192.168.0.0/24) + + $(call dk_network_parse_params,mynet@overlay@10.0.0.0/8) + $(call mb_assert_eq,overlay,$(dk_network_parse_params_driver),target param should override variable) + $(call mb_assert_eq,10.0.0.0/8,$(dk_network_parse_params_subnet),target param should override variable) + + ## Cleanup + $(eval docker_network_mynet_driver :=) + $(eval docker_network_mynet_subnet :=) +endef + +###################################################################################### +# dk_network_create tests +###################################################################################### + +define test_modules_docker_dk_network_create_basic + $(eval mb_invoke_silent := $(mb_on)) + + ## Test basic create with defaults + $(eval $0_result := $(call dk_network_create,mynetwork)) + $(call mb_assert_eq,docker network create --driver bridge mynetwork;,$($0_result)) + + $(eval mb_invoke_silent := $(mb_off)) +endef + +define test_modules_docker_dk_network_create_with_driver + $(eval mb_invoke_silent := $(mb_on)) + + $(eval $0_result := $(call dk_network_create,mynetwork,overlay)) + $(call mb_assert_eq,docker network create --driver overlay mynetwork;,$($0_result)) + + $(eval mb_invoke_silent := $(mb_off)) +endef + +define test_modules_docker_dk_network_create_full + $(eval mb_invoke_silent := $(mb_on)) + + $(eval $0_result := $(call dk_network_create,mynetwork,bridge,172.20.0.0/16,172.20.0.1)) + $(call mb_assert_eq,docker network create --driver bridge --subnet 172.20.0.0/16 --gateway 172.20.0.1 mynetwork;,$($0_result)) + + $(eval mb_invoke_silent := $(mb_off)) +endef + +###################################################################################### +# dk_network_remove tests +###################################################################################### + +define test_modules_docker_dk_network_remove + $(eval mb_invoke_silent := $(mb_on)) + + $(eval $0_result := $(call dk_network_remove,mynetwork)) + $(call mb_assert_eq,docker network rm mynetwork;,$($0_result)) + + $(eval mb_invoke_silent := $(mb_off)) endef diff --git a/modules/containers/docker/functions.mk b/modules/containers/docker/functions.mk index 8edba3c..9d1090b 100644 --- a/modules/containers/docker/functions.mk +++ b/modules/containers/docker/functions.mk @@ -201,6 +201,83 @@ $(strip ) endef +###################################################################################### +# Network Functions +###################################################################################### + +## @function dk_network_parse_params +## @desc Parse network target parameters from format: name[@driver][@subnet][@gateway] +## @desc Resolution order: target param > variable docker_network__ > default +## @arg 1: params (required) - Params string, e.g., "mynet" or "mynet@overlay@172.20.0.0/16@172.20.0.1" +## @sets dk_network_parse_params_name - Network name +## @sets dk_network_parse_params_driver - Network driver (resolved) +## @sets dk_network_parse_params_subnet - Network subnet (resolved) +## @sets dk_network_parse_params_gateway - Network gateway (resolved) +## @example $(call dk_network_parse_params,mynet@overlay) +## @example Access: $(dk_network_parse_params_name), $(dk_network_parse_params_driver), etc. +define dk_network_parse_params +$(strip + $(eval $0_arg1_params := $(if $(value 1),$(strip $1),$(call mb_printf_error,$0: params string required))) + + $(if $(findstring @,$($0_arg1_params)),\ + $(eval $0_parts := $(subst @, ,$($0_arg1_params)))\ + $(eval $0_name := $(word 1,$($0_parts)))\ + $(eval $0_param_driver := $(word 2,$($0_parts)))\ + $(eval $0_param_subnet := $(word 3,$($0_parts)))\ + $(eval $0_param_gateway := $(word 4,$($0_parts)))\ + ,\ + $(eval $0_name := $($0_arg1_params))\ + $(eval $0_param_driver :=)\ + $(eval $0_param_subnet :=)\ + $(eval $0_param_gateway :=)\ + ) + + $(eval $0_driver := $(strip \ + $(if $($0_param_driver),$($0_param_driver),\ + $(if $(value docker_network_$($0_name)_driver),$(docker_network_$($0_name)_driver),\ + $(dk_network_default_driver))))) + + $(eval $0_subnet := $(strip \ + $(if $($0_param_subnet),$($0_param_subnet),\ + $(if $(value docker_network_$($0_name)_subnet),$(docker_network_$($0_name)_subnet),)))) + + $(eval $0_gateway := $(strip \ + $(if $($0_param_gateway),$($0_param_gateway),\ + $(if $(value docker_network_$($0_name)_gateway),$(docker_network_$($0_name)_gateway),)))) +) +endef + +## @function dk_network_create +## @desc Create a docker network with optional driver, subnet, and gateway +## @arg 1: name (required) - Network name +## @arg 2: driver (optional) - Network driver (default: bridge) +## @arg 3: subnet (optional) - Network subnet in CIDR notation, e.g., 172.20.0.0/16 +## @arg 4: gateway (optional) - Network gateway IP, e.g., 172.20.0.1 +define dk_network_create +$(strip + $(eval $0_arg1_name := $(if $(value 1),$(strip $1),$(call mb_printf_error,$0: network name required))) + $(eval $0_arg2_driver := $(if $(value 2),$(strip $2),bridge)) + $(eval $0_arg3_subnet := $(if $(value 3),$(strip $3))) + $(eval $0_arg4_gateway := $(if $(value 4),$(strip $4))) + + $(eval $0_opts := --driver $($0_arg2_driver)) + $(if $($0_arg3_subnet),$(eval $0_opts += --subnet $($0_arg3_subnet))) + $(if $($0_arg4_gateway),$(eval $0_opts += --gateway $($0_arg4_gateway))) + + $(call dk_invoke,network create,$($0_opts),$($0_arg1_name)) +) +endef + +## @function dk_network_remove +## @desc Remove a docker network +## @arg 1: name (required) - Network name to remove +define dk_network_remove +$(strip + $(eval $0_arg1_name := $(if $(value 1),$(strip $1),$(call mb_printf_error,$0: network name required))) + $(call dk_invoke,network rm,,$($0_arg1_name)) +) +endef + ###################################################################################### # mb_exec_with_mode handler ###################################################################################### diff --git a/modules/containers/docker/mod_config.mk b/modules/containers/docker/mod_config.mk index 6c29581..d3605c5 100644 --- a/modules/containers/docker/mod_config.mk +++ b/modules/containers/docker/mod_config.mk @@ -24,8 +24,12 @@ dk_exec_default_tty ?= -it# ## Default options for docker logs (non-blocking by default) dk_logs_default_opts ?= --tail=200# -## Default network name for docker/network-ensure target -dk_default_network_name ?=# +## Default network driver for docker/network/create and docker/network/ensure targets +dk_network_default_driver ?= bridge# + +## Suppress errors for network create (when exists) and remove (when missing) +## Set to 'true' to skip silently instead of failing +docker_network_ignore_errors ?=# ## Default command for running commands in containers dk_exec_default_dk_cmd ?= exec \ No newline at end of file diff --git a/modules/containers/docker/targets.mk b/modules/containers/docker/targets.mk index e2e51ec..851fca3 100644 --- a/modules/containers/docker/targets.mk +++ b/modules/containers/docker/targets.mk @@ -71,3 +71,75 @@ docker/clean-all: ## Remove all unused containers, images, volumes, and networks $(call mb_printf_info,Cleaning all unused Docker resources...) $(call dk_invoke,system prune,--volumes --force),\ $(call mb_printf_info,Cleanup cancelled)\ ) + +###################################################################################### +# Targets - Network Operations +###################################################################################### + +## docker/network/create: Create a docker network (fails if exists) +## Usage: docker/network/create/[@driver][@subnet][@gateway] +## Parameters (use @ as separator): +## name - Network name (required) +## driver - Network driver: bridge, overlay, host, none (default: bridge) +## subnet - Network subnet in CIDR notation (optional, e.g., 172.20.0.0/16) +## gateway - Network gateway IP (optional, e.g., 172.20.0.1) +## Configuration variables (used if target params not provided): +## docker_network__driver - Network driver +## docker_network__subnet - Network subnet +## docker_network__gateway - Network gateway +## To suppress errors when network exists, set: docker_network_ignore_errors=true +## Examples: +## make docker/network/create/myapp +## make docker/network/create/myapp@overlay +## make docker/network/create/myapp@bridge@172.20.0.0/16 +## make docker/network/create/myapp@bridge@172.20.0.0/16@172.20.0.1 +docker/network/create/%: ## Create a network (fails if exists). Usage: docker/network/create/[@driver][@subnet][@gateway] + $(call dk_network_parse_params,$*) + $(if $(call mb_is_true,$(call dk_network_exists,$(dk_network_parse_params_name))),\ + $(if $(call mb_is_true,$(docker_network_ignore_errors)),\ + $(call mb_printf_info,Network $(dk_network_parse_params_name) already exists (skipped))\ + ,\ + $(call mb_printf_error,Network $(dk_network_parse_params_name) already exists. Use docker/network/ensure instead)\ + ),\ + $(call mb_printf_info,Creating network $(dk_network_parse_params_name))\ + $(call dk_network_create,$(dk_network_parse_params_name),$(dk_network_parse_params_driver),$(dk_network_parse_params_subnet),$(dk_network_parse_params_gateway))\ + ) + +docker/network/create: # Wrapper for docker/network/create/% + $(call mb_printf_info,Usage: make docker/network/create/[@driver][@subnet][@gateway]) + +## docker/network/ensure: Ensure a docker network exists (create if missing) +## Usage: docker/network/ensure/[@driver][@subnet][@gateway] +## Parameters and configuration are identical to docker/network/create +## This target is idempotent - safe to call multiple times +## Examples: +## make docker/network/ensure/myapp +## make docker/network/ensure/myapp@overlay@172.20.0.0/16 +docker/network/ensure/%: ## Ensure network exists (create if missing). Usage: docker/network/ensure/[@driver][@subnet][@gateway] + $(call dk_network_parse_params,$*) + $(if $(call mb_is_true,$(call dk_network_exists,$(dk_network_parse_params_name))),\ + $(call mb_printf_info,Network $(dk_network_parse_params_name) already exists),\ + $(call mb_printf_info,Creating network $(dk_network_parse_params_name))\ + $(call dk_network_create,$(dk_network_parse_params_name),$(dk_network_parse_params_driver),$(dk_network_parse_params_subnet),$(dk_network_parse_params_gateway))\ + ) + +docker/network/ensure: # Wrapper for docker/network/ensure/% + $(call mb_printf_info,Usage: make docker/network/ensure/[@driver][@subnet][@gateway]) + +## docker/network/remove: Remove a docker network (fails if not exists) +## Usage: docker/network/remove/ +## To suppress errors when network doesn't exist, set: docker_network_ignore_errors=true +## Examples: +## make docker/network/remove/myapp +docker/network/remove/%: ## Remove a network (fails if not exists). Usage: docker/network/remove/ + $(if $(call mb_is_false,$(call dk_network_exists,$*)),\ + $(if $(call mb_is_true,$(docker_network_ignore_errors)),\ + $(call mb_printf_info,Network $* does not exist (skipped)),\ + $(call mb_printf_error,Network $* does not exist)\ + ),\ + $(call mb_printf_info,Removing network $*)\ + $(call dk_network_remove,$*)\ + ) + +docker/network/remove: # Wrapper for docker/network/remove/% + $(call mb_printf_info,Usage: make docker/network/remove/)