Skip to content

Commit 32edcc4

Browse files
committed
refactor: Use common --stages arg for cloud-init stages
Using multiple different conflicting names for the same things causes endless confusion. Standardize the commandline interface.
1 parent 00f711b commit 32edcc4

26 files changed

+57
-126
lines changed

cloudinit/cmd/main.py

Lines changed: 20 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,8 @@ def main_init(name, args):
394394
)
395395
return (None, [])
396396
except sources.DataSourceNotFoundException:
397-
# In the case of 'cloud-init init' without '--local' it is a bit
398-
# more likely that the user would consider it failure if nothing was
399-
# found.
397+
# In the case of 'cloud-init --stage=init' it is a bit more likely that
398+
# the user would consider it failure if nothing was found.
400399
if mode == sources.DSMODE_LOCAL:
401400
LOG.debug("No local datasource found")
402401
else:
@@ -845,6 +844,12 @@ def _maybe_set_hostname(init, stage, retry_stage):
845844
def main_features(name, args):
846845
sys.stdout.write("\n".join(sorted(version.FEATURES)) + "\n")
847846

847+
STAGE_FROM_NAME = {
848+
"local": main_init,
849+
"network": main_init,
850+
"config": main_modules,
851+
"final": main_modules,
852+
}
848853

849854
def main(sysv_args=None):
850855
configure_root_logger()
@@ -885,40 +890,18 @@ def main(sysv_args=None):
885890
dest="force",
886891
default=False,
887892
)
893+
parser.add_argument(
894+
"--stage",
895+
action="store",
896+
help="Cloud-init stage to start",
897+
choices=("init", "network", "config", "final"),
898+
default=None,
899+
)
888900

889901
parser.set_defaults(reporter=None)
890902
subparsers = parser.add_subparsers(title="Subcommands", dest="subcommand")
891903
subparsers.required = True
892904

893-
# Each action and its sub-options (if any)
894-
parser_init = subparsers.add_parser(
895-
"init", help="Initialize cloud-init and perform initial modules."
896-
)
897-
parser_init.add_argument(
898-
"--local",
899-
"-l",
900-
action="store_true",
901-
help="Start in local mode (default: %(default)s).",
902-
default=False,
903-
)
904-
# This is used so that we can know which action is selected +
905-
# the functor to use to run this subcommand
906-
parser_init.set_defaults(action=("init", main_init))
907-
908-
# These settings are used for the 'config' and 'final' stages
909-
parser_mod = subparsers.add_parser(
910-
"modules", help="Activate modules using a given configuration key."
911-
)
912-
parser_mod.add_argument(
913-
"--mode",
914-
"-m",
915-
action="store",
916-
help="Module configuration name to use (default: %(default)s).",
917-
default="config",
918-
choices=("init", "config", "final"),
919-
)
920-
parser_mod.set_defaults(action=("modules", main_modules))
921-
922905
# This subcommand allows you to run a single module
923906
parser_single = subparsers.add_parser(
924907
"single", help="Run a single module."
@@ -1042,9 +1025,7 @@ def main(sysv_args=None):
10421025
parser_status.set_defaults(action=("status", handle_status_args))
10431026

10441027
args = parser.parse_args(args=sysv_args)
1045-
1046-
# Subparsers.required = True and each subparser sets action=(name, functor)
1047-
(name, functor) = args.action
1028+
name = args.stage
10481029

10491030
# Setup basic logging to start (until reinitialized)
10501031
# iff in debug mode.
@@ -1053,23 +1034,10 @@ def main(sysv_args=None):
10531034

10541035
# Setup signal handlers before running
10551036
signal_handler.attach_handlers()
1056-
1057-
# Write boot stage data to write status.json and result.json
1058-
# Exclude modules --mode=init, since it is not a real boot stage and
1059-
# should not be written into status.json
1060-
if "init" == name or ("modules" == name and "init" != args.mode):
1061-
functor = status_wrapper
1062-
1063-
rname = None
10641037
report_on = True
1065-
if name == "init":
1066-
if args.local:
1067-
rname, rdesc = ("init-local", "searching for local datasources")
1068-
else:
1069-
rname, rdesc = (
1070-
"init-network",
1071-
"searching for network datasources",
1072-
)
1038+
if name in ["local", "network", "config", "final"]:
1039+
rname, rdesc = name, f"running in stage {name}"
1040+
args.action = (name, STAGE_FROM_NAME[args.stage])
10731041
elif name == "modules":
10741042
rname, rdesc = (
10751043
"modules-%s" % args.mode,
@@ -1095,7 +1063,7 @@ def main(sysv_args=None):
10951063
logfunc=LOG.debug,
10961064
msg="cloud-init mode '%s'" % name,
10971065
get_uptime=True,
1098-
func=functor,
1066+
func=status_wrapper,
10991067
args=(name, args),
11001068
)
11011069
reporting.flush_events()

doc/rtd/howto/identify_datasource.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,5 @@ re-run, then clean up any logs, and finally, re-run ``cloud-init``:
5151
5252
sudo DI_LOG=stderr /usr/lib/cloud-init/ds-identify --force
5353
sudo cloud-init clean --logs
54-
sudo cloud-init init --local
55-
sudo cloud-init init
54+
sudo cloud-init --stage=local
55+
sudo cloud-init --stage=init

doc/rtd/reference/cli.rst

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Example output:
1515

1616
.. code-block::
1717
18-
usage: cloud-init [-h] [--version] [--file FILES] [--debug] [--force]
19-
{init,modules,single,query,features,analyze,devel,collect-logs,clean,status,schema} ...
18+
usage: cloud-init [-h] [--version] [--file FILES] [--debug] [--force] [--stage STAGE]
19+
{single,query,features,analyze,devel,collect-logs,clean,status,schema} ...
2020
2121
options:
2222
-h, --help show this help message and exit
@@ -25,11 +25,10 @@ Example output:
2525
Use additional yaml configuration files.
2626
--debug, -d Show additional pre-action logging (default: False).
2727
--force Force running even if no datasource is found (use at your own risk).
28+
--stage Specify which stage to run {local,network,config,final}
2829
2930
Subcommands:
3031
{init,modules,single,query,features,analyze,devel,collect-logs,clean,status,schema}
31-
init Initialize cloud-init and perform initial modules.
32-
modules Activate modules using a given configuration key.
3332
single Run a single module.
3433
query Query standardized instance metadata from the command line.
3534
features List defined features.
@@ -160,42 +159,6 @@ Example output:
160159
NETWORK_CONFIG_V1
161160
NETWORK_CONFIG_V2
162161
163-
164-
.. _cli_init:
165-
166-
:command:`init`
167-
===============
168-
169-
Generally run by OS init systems to execute ``cloud-init``'s stages:
170-
*init* and *init-local*. See :ref:`boot_stages` for more info.
171-
Can be run on the commandline, but is generally gated to run only once
172-
due to semaphores in :file:`/var/lib/cloud/instance/sem/` and
173-
:file:`/var/lib/cloud/sem`.
174-
175-
* :command:`--local`: Run *init-local* stage instead of *init*.
176-
177-
.. _cli_modules:
178-
179-
:command:`modules`
180-
==================
181-
182-
Generally run by OS init systems to execute ``modules:config`` and
183-
``modules:final`` boot stages. This executes cloud config :ref:`modules`
184-
configured to run in the Init, Config and Final stages. The modules are
185-
declared to run in various boot stages in the file
186-
:file:`/etc/cloud/cloud.cfg` under keys:
187-
188-
* ``cloud_init_modules``
189-
* ``cloud_config_modules``
190-
* ``cloud_final_modules``
191-
192-
Can be run on the command line, but each module is gated to run only once due
193-
to semaphores in :file:`/var/lib/cloud/`.
194-
195-
* :command:`--mode [init|config|final]`: Run ``modules:init``,
196-
``modules:config`` or ``modules:final`` ``cloud-init`` stages.
197-
See :ref:`boot_stages` for more info.
198-
199162
.. _cli_query:
200163

201164
:command:`query`

systemd/cloud-config.service.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled
1111

1212
[Service]
1313
Type=oneshot
14-
ExecStart=/usr/bin/cloud-init modules --mode=config
14+
ExecStart=/usr/bin/cloud-init --stage=config
1515
RemainAfterExit=yes
1616
TimeoutSec=0
1717

systemd/cloud-final.service.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled
1414

1515
[Service]
1616
Type=oneshot
17-
ExecStart=/usr/bin/cloud-init modules --mode=final
17+
ExecStart=/usr/bin/cloud-init --stage=final
1818
RemainAfterExit=yes
1919
TimeoutSec=0
2020
KillMode=process
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ ExecStartPre=/bin/mkdir -p /run/cloud-init
3737
ExecStartPre=/sbin/restorecon /run/cloud-init
3838
ExecStartPre=/usr/bin/touch /run/cloud-init/enabled
3939
{% endif %}
40-
ExecStart=/usr/bin/cloud-init init --local
40+
ExecStart=/usr/bin/cloud-init --stage init
4141
RemainAfterExit=yes
4242
TimeoutSec=0
4343

systemd/cloud-network.service.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled
4444

4545
[Service]
4646
Type=oneshot
47-
ExecStart=/usr/bin/cloud-init init
47+
ExecStart=/usr/bin/cloud-init --stage init
4848
RemainAfterExit=yes
4949
TimeoutSec=0
5050

sysvinit/debian/cloud-config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Required-Stop:
66
# Default-Start: 2 3 4 5
77
# Default-Stop: 0 1 6
8-
# Short-Description: Cloud init modules --mode config
8+
# Short-Description: Cloud init --stage=config
99
# Description: Cloud configuration initialization
1010
### END INIT INFO
1111

@@ -17,7 +17,7 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin
1717
DESC="Cloud service"
1818
NAME=cloud-init
1919
DAEMON=/usr/bin/$NAME
20-
DAEMON_ARGS="modules --mode config"
20+
DAEMON_ARGS="--stage=config"
2121
SCRIPTNAME=/etc/init.d/$NAME
2222

2323
# Exit if the package is not installed

sysvinit/debian/cloud-final

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Required-Stop:
66
# Default-Start: 2 3 4 5
77
# Default-Stop: 0 1 6
8-
# Short-Description: Cloud init modules final jobs
8+
# Short-Description: Cloud init final stage
99
# Description: This runs the cloud configuration initialization "final" jobs
1010
# and can be seen as the traditional "rc.local" time for the cloud.
1111
# It runs after all cloud-config jobs are run
@@ -19,7 +19,7 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin
1919
DESC="Cloud service"
2020
NAME=cloud-init
2121
DAEMON=/usr/bin/$NAME
22-
DAEMON_ARGS="modules --mode final"
22+
DAEMON_ARGS="--stage=config"
2323
SCRIPTNAME=/etc/init.d/$NAME
2424

2525
# Exit if the package is not installed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Required-Stop:
66
# Default-Start: 2 3 4 5
77
# Default-Stop: 0 1 6
8-
# Short-Description: Cloud init local
8+
# Short-Description: Cloud-init local stage
99
# Description: Cloud configuration initialization
1010
### END INIT INFO
1111

@@ -16,7 +16,7 @@ PATH=/sbin:/usr/sbin:/bin:/usr/bin
1616
DESC="Cloud service"
1717
NAME=cloud-init
1818
DAEMON=/usr/bin/$NAME
19-
DAEMON_ARGS="init --local"
19+
DAEMON_ARGS="--stage=local"
2020
SCRIPTNAME=/etc/init.d/$NAME
2121

2222
# Exit if the package is not installed

0 commit comments

Comments
 (0)