Add support for subcommands to "boulder" command (#6426)
Boulder builds a single binary which is symlinked to the different binary names, which are included in its releases. However, requiring symlinks isn't always convenient. This change makes the base `boulder` command usable as any of the other binary names. If the binary is invoked as boulder, runs the second argument as the command name. It shifts off the `boulder` from os.Args so that all the existing argument parsing can remain unchanged. This uses the subcommand versions in integration tests, which I think is important to verify this change works, however we can debate whether or not that should be merged, since we're using the symlink method in production, that's what we want to test. Issue #6362 suggests we want to move to a more fully-featured command-line parsing library that has proper subcommand support. This fixes one fragment of that, by providing subcommands, but is definitely nowhere near as nice as it could be with a more fully fleshed out library. Thus this change takes a minimal-touch approach to this change, since we know a larger refactoring is coming.
This commit is contained in:
parent
bdd9ad9941
commit
1d16ff9b00
|
@ -42,14 +42,23 @@ func main() {
|
|||
|
||||
func init() {
|
||||
cmd.RegisterCommand("boulder", func() {
|
||||
if len(os.Args) > 1 && os.Args[1] == "--list" {
|
||||
for _, c := range cmd.AvailableCommands() {
|
||||
if c != "boulder" {
|
||||
fmt.Println(c)
|
||||
}
|
||||
if len(os.Args) <= 1 {
|
||||
fmt.Fprintf(os.Stderr, "Call with --list to list available subcommands. Run them like boulder <subcommand>.\n")
|
||||
return
|
||||
}
|
||||
subcommand := cmd.LookupCommand(os.Args[1])
|
||||
if subcommand == nil {
|
||||
fmt.Fprintf(os.Stderr, "Unknown subcommand '%s'.\n", os.Args[1])
|
||||
return
|
||||
}
|
||||
os.Args = os.Args[1:]
|
||||
subcommand()
|
||||
})
|
||||
cmd.RegisterCommand("--list", func() {
|
||||
for _, c := range cmd.AvailableCommands() {
|
||||
if c != "boulder" && c != "--list" {
|
||||
fmt.Println(c)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Call with --list to list available subcommands. Symlink and run as a subcommand to run that subcommand.\n")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ def test_single_ocsp():
|
|||
This is a non-API test.
|
||||
"""
|
||||
p = subprocess.Popen(
|
||||
["./bin/ocsp-responder", "--config", "test/issuer-ocsp-responder.json"])
|
||||
["./bin/boulder", "ocsp-responder", "--config", "test/issuer-ocsp-responder.json"])
|
||||
waitport(4003, ' '.join(p.args))
|
||||
|
||||
# Verify that the static OCSP responder, which answers with a
|
||||
|
@ -218,7 +218,7 @@ def check_balance():
|
|||
% address)
|
||||
|
||||
def run_cert_checker():
|
||||
run(["./bin/cert-checker", "-config", "%s/cert-checker.json" % config_dir])
|
||||
run(["./bin/boulder", "cert-checker", "-config", "%s/cert-checker.json" % config_dir])
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
)
|
||||
|
||||
func setup() (*exec.Cmd, *bytes.Buffer, akamaipb.AkamaiPurgerClient, error) {
|
||||
purgerCmd := exec.Command("./bin/akamai-purger", "--config", "test/integration/testdata/akamai-purger-queue-drain-config.json")
|
||||
purgerCmd := exec.Command("./bin/boulder", "akamai-purger", "--config", "test/integration/testdata/akamai-purger-queue-drain-config.json")
|
||||
var outputBuffer bytes.Buffer
|
||||
purgerCmd.Stdout = &outputBuffer
|
||||
purgerCmd.Stderr = &outputBuffer
|
||||
|
|
|
@ -25,7 +25,7 @@ func TestCAALogChecker(t *testing.T) {
|
|||
test.AssertEquals(t, len(result.Order.Authorizations), 1)
|
||||
|
||||
// Should be no specific output, since everything is good
|
||||
cmd := exec.Command("bin/caa-log-checker", "-ra-log", "/var/log/boulder-ra.log", "-va-logs", "/var/log/boulder-va.log")
|
||||
cmd := exec.Command("bin/boulder", "caa-log-checker", "-ra-log", "/var/log/boulder-ra.log", "-va-logs", "/var/log/boulder-va.log")
|
||||
stdErr := new(bytes.Buffer)
|
||||
cmd.Stderr = stdErr
|
||||
out, err := cmd.Output()
|
||||
|
@ -41,7 +41,7 @@ func TestCAALogChecker(t *testing.T) {
|
|||
tmp, err := os.CreateTemp(os.TempDir(), "boulder-va-empty")
|
||||
test.AssertNotError(t, err, "failed to create temporary file")
|
||||
defer os.Remove(tmp.Name())
|
||||
cmd = exec.Command("bin/caa-log-checker", "-ra-log", "/var/log/boulder-ra.log", "-va-logs", tmp.Name())
|
||||
cmd = exec.Command("bin/boulder", "caa-log-checker", "-ra-log", "/var/log/boulder-ra.log", "-va-logs", tmp.Name())
|
||||
stdErr = new(bytes.Buffer)
|
||||
cmd.Stderr = stdErr
|
||||
out, err = cmd.Output()
|
||||
|
|
|
@ -21,10 +21,10 @@ import (
|
|||
func runUpdater(t *testing.T, configFile string) {
|
||||
t.Helper()
|
||||
|
||||
binPath, err := filepath.Abs("bin/crl-updater")
|
||||
test.AssertNotError(t, err, "computing crl-updater path")
|
||||
binPath, err := filepath.Abs("bin/boulder")
|
||||
test.AssertNotError(t, err, "computing boulder binary path")
|
||||
|
||||
c := exec.Command(binPath, "-config", configFile, "-debug-addr", ":8022", "-runOnce")
|
||||
c := exec.Command(binPath, "crl-updater", "-config", configFile, "-debug-addr", ":8022", "-runOnce")
|
||||
out, err := c.CombinedOutput()
|
||||
test.AssertNotError(t, err, fmt.Sprintf("crl-updater failed: %s", out))
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ func TestOrphanFinder(t *testing.T) {
|
|||
io.WriteString(f, fmt.Sprintf(template, precert.SerialNumber.Bytes(),
|
||||
precert.Raw, cert.SerialNumber.Bytes(), cert.Raw))
|
||||
f.Close()
|
||||
cmd := exec.Command("./bin/orphan-finder", "parse-ca-log",
|
||||
cmd := exec.Command("./bin/boulder", "orphan-finder", "parse-ca-log",
|
||||
"--config", "./"+os.Getenv("BOULDER_CONFIG_DIR")+"/orphan-finder.json",
|
||||
"--log-file", f.Name())
|
||||
out, err := cmd.Output()
|
||||
|
|
|
@ -16,30 +16,30 @@ Service = collections.namedtuple('Service', ('name', 'debug_port', 'grpc_addr',
|
|||
SERVICES = (
|
||||
Service('boulder-remoteva-a',
|
||||
8011, 'rva1.service.consul:9097',
|
||||
('./bin/boulder-remoteva', '--config', os.path.join(config_dir, 'va-remote-a.json')),
|
||||
('./bin/boulder', 'boulder-remoteva', '--config', os.path.join(config_dir, 'va-remote-a.json')),
|
||||
None),
|
||||
Service('boulder-remoteva-b',
|
||||
8012, 'rva1.service.consul:9098',
|
||||
('./bin/boulder-remoteva', '--config', os.path.join(config_dir, 'va-remote-b.json')),
|
||||
('./bin/boulder', 'boulder-remoteva', '--config', os.path.join(config_dir, 'va-remote-b.json')),
|
||||
None),
|
||||
Service('boulder-sa-1',
|
||||
8003, 'sa1.service.consul:9095',
|
||||
('./bin/boulder-sa', '--config', os.path.join(config_dir, 'sa.json'), '--addr', 'sa1.service.consul:9095', '--debug-addr', ':8003'),
|
||||
('./bin/boulder', 'boulder-sa', '--config', os.path.join(config_dir, 'sa.json'), '--addr', 'sa1.service.consul:9095', '--debug-addr', ':8003'),
|
||||
None),
|
||||
Service('boulder-sa-2',
|
||||
8103, 'sa2.service.consul:9095',
|
||||
('./bin/boulder-sa', '--config', os.path.join(config_dir, 'sa.json'), '--addr', 'sa2.service.consul:9095', '--debug-addr', ':8103'),
|
||||
('./bin/boulder', 'boulder-sa', '--config', os.path.join(config_dir, 'sa.json'), '--addr', 'sa2.service.consul:9095', '--debug-addr', ':8103'),
|
||||
None),
|
||||
Service('ct-test-srv',
|
||||
4500, None,
|
||||
('./bin/ct-test-srv', '--config', 'test/ct-test-srv/ct-test-srv.json'), None),
|
||||
Service('boulder-publisher-1',
|
||||
8009, 'publisher1.service.consul:9091',
|
||||
('./bin/boulder-publisher', '--config', os.path.join(config_dir, 'publisher.json'), '--addr', 'publisher1.service.consul:9091', '--debug-addr', ':8009'),
|
||||
('./bin/boulder', 'boulder-publisher', '--config', os.path.join(config_dir, 'publisher.json'), '--addr', 'publisher1.service.consul:9091', '--debug-addr', ':8009'),
|
||||
None),
|
||||
Service('boulder-publisher-2',
|
||||
8109, 'publisher2.service.consul:9091',
|
||||
('./bin/boulder-publisher', '--config', os.path.join(config_dir, 'publisher.json'), '--addr', 'publisher2.service.consul:9091', '--debug-addr', ':8109'),
|
||||
('./bin/boulder', 'boulder-publisher', '--config', os.path.join(config_dir, 'publisher.json'), '--addr', 'publisher2.service.consul:9091', '--debug-addr', ':8109'),
|
||||
None),
|
||||
Service('mail-test-srv',
|
||||
9380, None,
|
||||
|
@ -47,23 +47,23 @@ SERVICES = (
|
|||
None),
|
||||
Service('ocsp-responder',
|
||||
8005, None,
|
||||
('./bin/ocsp-responder', '--config', os.path.join(config_dir, 'ocsp-responder.json')),
|
||||
('./bin/boulder', 'ocsp-responder', '--config', os.path.join(config_dir, 'ocsp-responder.json')),
|
||||
('boulder-ra-1', 'boulder-ra-2')),
|
||||
Service('boulder-va-1',
|
||||
8004, 'va1.service.consul:9092',
|
||||
('./bin/boulder-va', '--config', os.path.join(config_dir, 'va.json'), '--addr', 'va1.service.consul:9092', '--debug-addr', ':8004'),
|
||||
('./bin/boulder', 'boulder-va', '--config', os.path.join(config_dir, 'va.json'), '--addr', 'va1.service.consul:9092', '--debug-addr', ':8004'),
|
||||
('boulder-remoteva-a', 'boulder-remoteva-b')),
|
||||
Service('boulder-va-2',
|
||||
8104, 'va2.service.consul:9092',
|
||||
('./bin/boulder-va', '--config', os.path.join(config_dir, 'va.json'), '--addr', 'va2.service.consul:9092', '--debug-addr', ':8104'),
|
||||
('./bin/boulder', 'boulder-va', '--config', os.path.join(config_dir, 'va.json'), '--addr', 'va2.service.consul:9092', '--debug-addr', ':8104'),
|
||||
('boulder-remoteva-a', 'boulder-remoteva-b')),
|
||||
Service('boulder-ca-a',
|
||||
8001, 'ca1.service.consul:9093',
|
||||
('./bin/boulder-ca', '--config', os.path.join(config_dir, 'ca-a.json'), '--ca-addr', 'ca1.service.consul:9093', '--ocsp-addr', 'ca1.service.consul:9096', '--crl-addr', 'ca1.service.consul:9106', '--debug-addr', ':8001'),
|
||||
('./bin/boulder', 'boulder-ca', '--config', os.path.join(config_dir, 'ca-a.json'), '--ca-addr', 'ca1.service.consul:9093', '--ocsp-addr', 'ca1.service.consul:9096', '--crl-addr', 'ca1.service.consul:9106', '--debug-addr', ':8001'),
|
||||
('boulder-sa-1', 'boulder-sa-2')),
|
||||
Service('boulder-ca-b',
|
||||
8101, 'ca2.service.consul:9093',
|
||||
('./bin/boulder-ca', '--config', os.path.join(config_dir, 'ca-b.json'), '--ca-addr', 'ca2.service.consul:9093', '--ocsp-addr', 'ca2.service.consul:9096', '--crl-addr', 'ca2.service.consul:9106', '--debug-addr', ':8101'),
|
||||
('./bin/boulder', 'boulder-ca', '--config', os.path.join(config_dir, 'ca-b.json'), '--ca-addr', 'ca2.service.consul:9093', '--ocsp-addr', 'ca2.service.consul:9096', '--crl-addr', 'ca2.service.consul:9106', '--debug-addr', ':8101'),
|
||||
('boulder-sa-1', 'boulder-sa-2')),
|
||||
Service('akamai-test-srv',
|
||||
6789, None,
|
||||
|
@ -71,7 +71,7 @@ SERVICES = (
|
|||
None),
|
||||
Service('akamai-purger',
|
||||
9666, None,
|
||||
('./bin/akamai-purger', '--config', os.path.join(config_dir, 'akamai-purger.json')),
|
||||
('./bin/boulder', 'akamai-purger', '--config', os.path.join(config_dir, 'akamai-purger.json')),
|
||||
('akamai-test-srv',)),
|
||||
Service('s3-test-srv',
|
||||
7890, None,
|
||||
|
@ -79,43 +79,43 @@ SERVICES = (
|
|||
None),
|
||||
Service('crl-storer',
|
||||
9667, None,
|
||||
('./bin/crl-storer', '--config', os.path.join(config_dir, 'crl-storer.json')),
|
||||
('./bin/boulder', 'crl-storer', '--config', os.path.join(config_dir, 'crl-storer.json')),
|
||||
('s3-test-srv',)),
|
||||
Service('ocsp-updater',
|
||||
8006, None,
|
||||
('./bin/ocsp-updater', '--config', os.path.join(config_dir, 'ocsp-updater.json')),
|
||||
('./bin/boulder', 'ocsp-updater', '--config', os.path.join(config_dir, 'ocsp-updater.json')),
|
||||
('boulder-ca-a', 'boulder-ca-b')),
|
||||
Service('crl-updater',
|
||||
8021, None,
|
||||
('./bin/crl-updater', '--config', os.path.join(config_dir, 'crl-updater.json')),
|
||||
('./bin/boulder', 'crl-updater', '--config', os.path.join(config_dir, 'crl-updater.json')),
|
||||
('boulder-ca-a', 'boulder-ca-b', 'boulder-sa-1', 'boulder-sa-2', 'crl-storer')),
|
||||
Service('boulder-ra-1',
|
||||
8002, 'ra1.service.consul:9094',
|
||||
('./bin/boulder-ra', '--config', os.path.join(config_dir, 'ra.json'), '--addr', 'ra1.service.consul:9094', '--debug-addr', ':8002'),
|
||||
('./bin/boulder', 'boulder-ra', '--config', os.path.join(config_dir, 'ra.json'), '--addr', 'ra1.service.consul:9094', '--debug-addr', ':8002'),
|
||||
('boulder-sa-1', 'boulder-sa-2', 'boulder-ca-a', 'boulder-ca-b', 'boulder-va-1', 'boulder-va-2', 'akamai-purger', 'boulder-publisher-1', 'boulder-publisher-2')),
|
||||
Service('boulder-ra-2',
|
||||
8102, 'ra2.service.consul:9094',
|
||||
('./bin/boulder-ra', '--config', os.path.join(config_dir, 'ra.json'), '--addr', 'ra2.service.consul:9094', '--debug-addr', ':8102'),
|
||||
('./bin/boulder', 'boulder-ra', '--config', os.path.join(config_dir, 'ra.json'), '--addr', 'ra2.service.consul:9094', '--debug-addr', ':8102'),
|
||||
('boulder-sa-1', 'boulder-sa-2', 'boulder-ca-a', 'boulder-ca-b', 'boulder-va-1', 'boulder-va-2', 'akamai-purger', 'boulder-publisher-1', 'boulder-publisher-2')),
|
||||
Service('bad-key-revoker',
|
||||
8020, None,
|
||||
('./bin/bad-key-revoker', '--config', os.path.join(config_dir, 'bad-key-revoker.json')),
|
||||
('./bin/boulder', 'bad-key-revoker', '--config', os.path.join(config_dir, 'bad-key-revoker.json')),
|
||||
('boulder-ra-1', 'boulder-ra-2', 'mail-test-srv')),
|
||||
Service('nonce-service-taro',
|
||||
8111, 'nonce1.service.consul:9101',
|
||||
('./bin/nonce-service', '--config', os.path.join(config_dir, 'nonce.json'), '--addr', 'nonce1.service.consul:9101', '--debug-addr', ':8111', '--prefix', 'taro'),
|
||||
('./bin/boulder', 'nonce-service', '--config', os.path.join(config_dir, 'nonce.json'), '--addr', 'nonce1.service.consul:9101', '--debug-addr', ':8111', '--prefix', 'taro'),
|
||||
None),
|
||||
Service('nonce-service-zinc',
|
||||
8112, 'nonce2.service.consul:9101',
|
||||
('./bin/nonce-service', '--config', os.path.join(config_dir, 'nonce.json'), '--addr', 'nonce2.service.consul:9101', '--debug-addr', ':8112', '--prefix', 'zinc'),
|
||||
('./bin/boulder', 'nonce-service', '--config', os.path.join(config_dir, 'nonce.json'), '--addr', 'nonce2.service.consul:9101', '--debug-addr', ':8112', '--prefix', 'zinc'),
|
||||
None),
|
||||
Service('boulder-wfe2',
|
||||
4001, None,
|
||||
('./bin/boulder-wfe2', '--config', os.path.join(config_dir, 'wfe2.json')),
|
||||
('./bin/boulder', 'boulder-wfe2', '--config', os.path.join(config_dir, 'wfe2.json')),
|
||||
('boulder-ra-1', 'boulder-ra-2', 'boulder-sa-1', 'boulder-sa-2', 'nonce-service-taro', 'nonce-service-zinc')),
|
||||
Service('log-validator',
|
||||
8016, None,
|
||||
('./bin/log-validator', '--config', os.path.join(config_dir, 'log-validator.json')),
|
||||
('./bin/boulder', 'log-validator', '--config', os.path.join(config_dir, 'log-validator.json')),
|
||||
None),
|
||||
)
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@ LOGFILE=/tmp/boulder.log
|
|||
docker logs boulder_tests > ${LOGFILE}
|
||||
|
||||
# Expect success
|
||||
./bin/caa-log-checker -ra-log ${LOGFILE} -va-logs ${LOGFILE}
|
||||
./bin/boulder caa-log-checker -ra-log ${LOGFILE} -va-logs ${LOGFILE}
|
||||
|
||||
# Expect error
|
||||
./bin/caa-log-checker -ra-log ${LOGFILE} -va-logs /dev/null >/tmp/output 2>&1 &&
|
||||
./bin/boulder caa-log-checker -ra-log ${LOGFILE} -va-logs /dev/null >/tmp/output 2>&1 &&
|
||||
(echo "caa-log-checker succeeded when it should have failed. Output:";
|
||||
cat /tmp/output;
|
||||
exit 9)
|
||||
|
|
|
@ -1503,7 +1503,7 @@ def test_expiration_mailer():
|
|||
requests.post("http://localhost:9381/clear", data='')
|
||||
for time in (no_reminder, first_reminder, last_reminder):
|
||||
print(get_future_output(
|
||||
["./bin/expiration-mailer", "--config", "%s/expiration-mailer.json" % config_dir],
|
||||
["./bin/boulder", "expiration-mailer", "--config", "%s/expiration-mailer.json" % config_dir],
|
||||
time))
|
||||
resp = requests.get("http://localhost:9381/count?to=%s" % email_addr)
|
||||
mailcount = int(resp.text)
|
||||
|
@ -1680,7 +1680,7 @@ def test_admin_revoker_cert():
|
|||
|
||||
# Revoke certificate by serial
|
||||
reset_akamai_purges()
|
||||
run(["./bin/admin-revoker", "serial-revoke",
|
||||
run(["./bin/boulder", "admin-revoker", "serial-revoke",
|
||||
"--config", "%s/admin-revoker.json" % config_dir,
|
||||
'%x' % parsed_cert.serial_number, '1'])
|
||||
|
||||
|
@ -1701,7 +1701,7 @@ def test_admin_revoker_batched():
|
|||
serialFile.write("%x\n" % parse_cert(order).serial_number)
|
||||
serialFile.close()
|
||||
|
||||
run(["./bin/admin-revoker", "batched-serial-revoke",
|
||||
run(["./bin/boulder", "admin-revoker", "batched-serial-revoke",
|
||||
"--config", "%s/admin-revoker.json" % config_dir,
|
||||
serialFile.name, '0', '2'])
|
||||
|
||||
|
|
Loading…
Reference in New Issue