Fix rendering of text flag defaults
This commit is contained in:
parent
af69f1cfba
commit
ca62a37692
@ -47,6 +47,10 @@ type Bootstrap struct {
|
||||
}
|
||||
|
||||
// New initializes and returns a new Bootstrap file for a new host.
|
||||
//
|
||||
// TODO in the resulting bootstrap only include this host and hosts which are
|
||||
// necessary for connecting to nebula/garage. Remember to immediately re-poll
|
||||
// garage for the full hosts list during network joining.
|
||||
func New(
|
||||
caCreds nebula.CACredentials,
|
||||
adminCreationParams CreationParams,
|
||||
|
@ -3,20 +3,37 @@ package main
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"isle/nebula"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
type textUnmarshalerFlag struct {
|
||||
inner interface {
|
||||
encoding.TextUnmarshaler
|
||||
type textUnmarshaler[T any] interface {
|
||||
encoding.TextUnmarshaler
|
||||
*T
|
||||
}
|
||||
|
||||
type textUnmarshalerFlag[T encoding.TextMarshaler, P textUnmarshaler[T]] struct {
|
||||
V T
|
||||
}
|
||||
|
||||
func (f *textUnmarshalerFlag[T, P]) Set(v string) error {
|
||||
return P(&(f.V)).UnmarshalText([]byte(v))
|
||||
}
|
||||
|
||||
func (f *textUnmarshalerFlag[T, P]) String() string {
|
||||
b, err := f.V.MarshalText()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("calling MarshalText on %#v: %v", f.V, err))
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (f textUnmarshalerFlag) Set(v string) error {
|
||||
return f.inner.UnmarshalText([]byte(v))
|
||||
}
|
||||
func (f *textUnmarshalerFlag[T, P]) Type() string { return "string" }
|
||||
|
||||
func (f textUnmarshalerFlag) String() string {
|
||||
return fmt.Sprint(f.inner)
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func (f textUnmarshalerFlag) Type() string { return "string" }
|
||||
type (
|
||||
hostNameFlag = textUnmarshalerFlag[nebula.HostName, *nebula.HostName]
|
||||
ipNetFlag = textUnmarshalerFlag[nebula.IPNet, *nebula.IPNet]
|
||||
ipFlag = textUnmarshalerFlag[netip.Addr, *netip.Addr]
|
||||
)
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"isle/bootstrap"
|
||||
"isle/daemon"
|
||||
"isle/jsonutil"
|
||||
"isle/nebula"
|
||||
"net/netip"
|
||||
"os"
|
||||
"sort"
|
||||
)
|
||||
@ -19,19 +17,17 @@ var subCmdHostsCreate = subCmd{
|
||||
do: func(subCmdCtx subCmdCtx) error {
|
||||
var (
|
||||
flags = subCmdCtx.flagSet(false)
|
||||
hostName nebula.HostName
|
||||
ip netip.Addr
|
||||
hostName hostNameFlag
|
||||
ip ipFlag
|
||||
)
|
||||
|
||||
hostNameF := flags.VarPF(
|
||||
textUnmarshalerFlag{&hostName},
|
||||
&hostName,
|
||||
"hostname", "h",
|
||||
"Name of the host to generate bootstrap.json for",
|
||||
)
|
||||
|
||||
flags.VarP(
|
||||
textUnmarshalerFlag{&ip}, "ip", "i", "IP of the new host",
|
||||
)
|
||||
flags.VarP(&ip, "ip", "i", "IP of the new host. An available IP will be chosen if none is given.")
|
||||
|
||||
canCreateHosts := flags.Bool(
|
||||
"can-create-hosts",
|
||||
@ -53,9 +49,9 @@ var subCmdHostsCreate = subCmd{
|
||||
&res,
|
||||
"CreateHost",
|
||||
daemon.CreateHostRequest{
|
||||
HostName: hostName,
|
||||
HostName: hostName.V,
|
||||
Opts: daemon.CreateHostOpts{
|
||||
IP: ip,
|
||||
IP: ip.V,
|
||||
CanCreateHosts: *canCreateHosts,
|
||||
},
|
||||
},
|
||||
@ -110,11 +106,11 @@ var subCmdHostsRemove = subCmd{
|
||||
do: func(subCmdCtx subCmdCtx) error {
|
||||
var (
|
||||
flags = subCmdCtx.flagSet(false)
|
||||
hostName nebula.HostName
|
||||
hostName hostNameFlag
|
||||
)
|
||||
|
||||
hostNameF := flags.VarPF(
|
||||
textUnmarshalerFlag{&hostName},
|
||||
&hostName,
|
||||
"hostname", "h",
|
||||
"Name of the host to remove",
|
||||
)
|
||||
@ -129,7 +125,7 @@ var subCmdHostsRemove = subCmd{
|
||||
|
||||
err := subCmdCtx.daemonRCPClient.Call(
|
||||
subCmdCtx.ctx, nil, "RemoveHost", daemon.RemoveHostRequest{
|
||||
HostName: hostName,
|
||||
HostName: hostName.V,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -15,11 +15,11 @@ var subCmdNebulaCreateCert = subCmd{
|
||||
do: func(subCmdCtx subCmdCtx) error {
|
||||
var (
|
||||
flags = subCmdCtx.flagSet(false)
|
||||
hostName nebula.HostName
|
||||
hostName hostNameFlag
|
||||
)
|
||||
|
||||
hostNameF := flags.VarPF(
|
||||
textUnmarshalerFlag{&hostName},
|
||||
&hostName,
|
||||
"hostname", "h",
|
||||
"Name of the host to generate a certificate for",
|
||||
)
|
||||
@ -53,7 +53,7 @@ var subCmdNebulaCreateCert = subCmd{
|
||||
&res,
|
||||
"CreateNebulaCertificate",
|
||||
daemon.CreateNebulaCertificateRequest{
|
||||
HostName: hostName,
|
||||
HostName: hostName.V,
|
||||
HostEncryptingPublicKey: hostPub,
|
||||
},
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"isle/daemon"
|
||||
"isle/jsonutil"
|
||||
"log"
|
||||
)
|
||||
|
||||
var subCmdNetworkCreate = subCmd{
|
||||
@ -14,28 +15,30 @@ var subCmdNetworkCreate = subCmd{
|
||||
var (
|
||||
ctx = subCmdCtx.ctx
|
||||
flags = subCmdCtx.flagSet(false)
|
||||
req daemon.CreateNetworkRequest
|
||||
|
||||
ipNet ipNetFlag
|
||||
hostName hostNameFlag
|
||||
)
|
||||
|
||||
flags.StringVarP(
|
||||
&req.Name, "name", "n", "",
|
||||
name := flags.StringP(
|
||||
"name", "n", "",
|
||||
"Human-readable name to identify the network as.",
|
||||
)
|
||||
|
||||
flags.StringVarP(
|
||||
&req.Domain, "domain", "d", "",
|
||||
domain := flags.StringP(
|
||||
"domain", "d", "",
|
||||
"Domain name that should be used as the root domain in the network.",
|
||||
)
|
||||
|
||||
ipNetF := flags.VarPF(
|
||||
textUnmarshalerFlag{&req.IPNet}, "ip-net", "i",
|
||||
&ipNet, "ip-net", "i",
|
||||
`An IP subnet, in CIDR form, which will be the overall range of`+
|
||||
` possible IPs in the network. The first IP in this network`+
|
||||
` range will become this first host's IP.`,
|
||||
)
|
||||
|
||||
hostNameF := flags.VarPF(
|
||||
textUnmarshalerFlag{&req.HostName},
|
||||
&hostName,
|
||||
"hostname", "h",
|
||||
"Name of this host, which will be the first host in the network",
|
||||
)
|
||||
@ -44,13 +47,23 @@ var subCmdNetworkCreate = subCmd{
|
||||
return fmt.Errorf("parsing flags: %w", err)
|
||||
}
|
||||
|
||||
if req.Name == "" ||
|
||||
req.Domain == "" ||
|
||||
if *name == "" ||
|
||||
*domain == "" ||
|
||||
!ipNetF.Changed ||
|
||||
!hostNameF.Changed {
|
||||
return errors.New("--name, --domain, --ip-net, and --hostname are required")
|
||||
}
|
||||
|
||||
req := daemon.CreateNetworkRequest{
|
||||
Name: *name,
|
||||
Domain: *domain,
|
||||
IPNet: ipNet.V,
|
||||
HostName: hostName.V,
|
||||
}
|
||||
|
||||
log.Printf("req:%+v", req)
|
||||
return nil
|
||||
|
||||
err := subCmdCtx.daemonRCPClient.Call(ctx, nil, "CreateNetwork", req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating network: %w", err)
|
||||
|
@ -48,6 +48,8 @@ func (ctx subCmdCtx) flagSet(withPassthrough bool) *pflag.FlagSet {
|
||||
passthroughStr = " [--] [args...]"
|
||||
}
|
||||
|
||||
// TODO don't allow -h/--help flag to be set by sub-commands (or better,
|
||||
// somehow check that a flag hasn't been set twice).
|
||||
fmt.Fprintf(
|
||||
os.Stderr, "%s[-h|--help] [%s flags...]%s\n\n",
|
||||
ctx.usagePrefix(), ctx.subCmd.name, passthroughStr,
|
||||
|
@ -32,6 +32,8 @@ type CreateHostOpts struct {
|
||||
// CanCreateHosts indicates that the bootstrap produced by CreateHost should
|
||||
// give the new host the ability to create new hosts as well.
|
||||
CanCreateHosts bool
|
||||
|
||||
// TODO add nebula cert tags
|
||||
}
|
||||
|
||||
// Daemon presents all functionality required for client frontends to interact
|
||||
@ -85,6 +87,9 @@ type Daemon interface {
|
||||
// existing host, given the public key for that host. This is currently
|
||||
// mostly useful for creating certs for mobile devices.
|
||||
//
|
||||
// TODO replace this with CreateHostBootstrap, and the
|
||||
// CreateNebulaCertificate RPC method can just pull cert out of that.
|
||||
//
|
||||
// Errors:
|
||||
// - ErrHostNotFound
|
||||
CreateNebulaCertificate(
|
||||
@ -685,6 +690,7 @@ func (d *daemon) CreateHost(
|
||||
)
|
||||
}
|
||||
}
|
||||
// TODO if the ip is given, check that it's not already in use.
|
||||
|
||||
caSigningPrivateKey, err := getNebulaCASigningPrivateKey(
|
||||
ctx, d.secretsStore,
|
||||
|
@ -11,6 +11,11 @@ var hostNameRegexp = regexp.MustCompile(`^[a-z][a-z0-9\-]*$`)
|
||||
// lowercase letters, numbers, and hyphens, and must start with a letter.
|
||||
type HostName string
|
||||
|
||||
// MarshalText casts the HostName to a byte string and returns it.
|
||||
func (h HostName) MarshalText() ([]byte, error) {
|
||||
return []byte(h), nil
|
||||
}
|
||||
|
||||
// UnmarshalText parses and validates a HostName from a text string.
|
||||
func (h *HostName) UnmarshalText(b []byte) error {
|
||||
if !hostNameRegexp.Match(b) {
|
||||
|
Loading…
Reference in New Issue
Block a user