Skip to content

Commit

Permalink
lndinit: add ability to write to k8s configmap
Browse files Browse the repository at this point in the history
We'll use this to write connection relateed information
for consumption by payment service proxy.
  • Loading branch information
calvinrzachman committed Jan 19, 2024
1 parent 97404fa commit 0238e58
Show file tree
Hide file tree
Showing 9 changed files with 367 additions and 50 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ initialization, including seed and password generation.
- [`gen-seed`](#gen-seed)
- [`load-secret`](#load-secret)
- [`store-secret`](#store-secret)
- [`store-configmap`](#store-configmap)
- [`init-wallet`](#init-wallet)
- [`wait-ready`](#wait-ready)
- [Example usage](#example-usage)
Expand Down Expand Up @@ -48,6 +49,9 @@ No `lnd` needed, but seed will be in `lnd`-specific [`aezeed` format](https://gi
### store-secret
`store-secret` interacts with kubernetes to write to secrets (no `lnd` needed)

### store-configmap
`store-configmap` interacts with kubernetes to write to configmaps (no `lnd` needed)

### init-wallet
`init-wallet` has two modes:
- `--init-type=file` creates an `lnd` specific `wallet.db` file
Expand Down
10 changes: 9 additions & 1 deletion cmd_gen_seed.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,15 @@ func (x *genSeedCommand) Execute(_ []string) error {

// Read passphrase from Kubernetes secret.
case x.PassphraseK8s.AnySet():
passPhrase, _, err = readK8s(x.PassphraseK8s)
k8sSecret := &k8sObjectOptions{
Namespace: x.PassphraseK8s.Namespace,
Name: x.PassphraseK8s.SecretName,
KeyName: x.PassphraseK8s.SecretKeyName,
Base64: x.PassphraseK8s.Base64,
ObjectType: ObjectTypeSecret,
}

passPhrase, _, err = readK8s(k8sSecret)

}
if err != nil {
Expand Down
11 changes: 6 additions & 5 deletions cmd_init_wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,13 @@ func (x *initWalletCommand) readInput(requireSeed bool) (string, string, string,

// Read passphrase from Kubernetes secret.
case storageK8s:
k8sSecret := &k8sSecretOptions{
k8sSecret := &k8sObjectOptions{
Namespace: x.K8s.Namespace,
SecretName: x.K8s.SecretName,
Name: x.K8s.SecretName,
KeyName: x.K8s.SeedKeyName,
Base64: x.K8s.Base64,
ObjectType: ObjectTypeSecret,
}
k8sSecret.SecretKeyName = x.K8s.SeedKeyName

if requireSeed {
log("Reading seed from k8s secret %s (namespace %s)",
Expand All @@ -260,7 +261,7 @@ func (x *initWalletCommand) readInput(requireSeed bool) (string, string, string,
log("Reading seed passphrase from k8s secret %s "+
"(namespace %s)", x.K8s.SecretName,
x.K8s.Namespace)
k8sSecret.SecretKeyName = x.K8s.SeedPassphraseKeyName
k8sSecret.KeyName = x.K8s.SeedPassphraseKeyName
seedPassPhrase, _, err = readK8s(k8sSecret)
if err != nil {
return "", "", "", err
Expand All @@ -269,7 +270,7 @@ func (x *initWalletCommand) readInput(requireSeed bool) (string, string, string,

log("Reading wallet password from k8s secret %s (namespace %s)",
x.K8s.SecretName, x.K8s.Namespace)
k8sSecret.SecretKeyName = x.K8s.WalletPasswordKeyName
k8sSecret.KeyName = x.K8s.WalletPasswordKeyName
walletPassword, _, err = readK8s(k8sSecret)
if err != nil {
return "", "", "", err
Expand Down
10 changes: 9 additions & 1 deletion cmd_load_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@ func (x *loadSecretCommand) Register(parser *flags.Parser) error {
func (x *loadSecretCommand) Execute(_ []string) error {
switch x.Source {
case storageK8s:
content, secret, err := readK8s(x.K8s)
objectOpts := &k8sObjectOptions{
Namespace: x.K8s.Namespace,
Name: x.K8s.SecretName,
KeyName: x.K8s.SecretKeyName,
Base64: x.K8s.Base64,
ObjectType: ObjectTypeSecret,
}

content, secret, err := readK8s(objectOpts)
if err != nil {
return fmt.Errorf("error reading secret %s in "+
"namespace %s: %v", x.K8s.SecretName,
Expand Down
130 changes: 130 additions & 0 deletions cmd_store_configmap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package main

import (
"fmt"
"io"
"os"
"path/filepath"

"github.com/jessevdk/go-flags"
)

type targetK8sConfigmap struct {
k8sConfigmapOptions

Helm *helmOptions `group:"Flags for configuring the Helm annotations (use when --target=k8s)" namespace:"helm"`
}

type storeConfigmapCommand struct {
Batch bool `long:"batch" description:"Instead of reading one configmap from stdin, read all files of the argument list and store them as entries in the configmap"`
Overwrite bool `long:"overwrite" description:"Overwrite existing configmap entries instead of aborting"`
Target string `long:"target" short:"t" description:"Configmap storage target" choice:"k8s"`
K8s *targetK8sConfigmap `group:"Flags for storing the key/value pair inside a Kubernetes Configmap (use when --target=k8s)" namespace:"k8s"`
}

func newStoreConfigmapCommand() *storeConfigmapCommand {
return &storeConfigmapCommand{
Target: storageK8s,
K8s: &targetK8sConfigmap{
k8sConfigmapOptions: k8sConfigmapOptions{
Namespace: defaultK8sNamespace,
},
},
}
}

func (x *storeConfigmapCommand) Register(parser *flags.Parser) error {
_, err := parser.AddCommand(
"store-configmap",
"Write key/value pairs to a Kubernetes configmap",
"Read a configmap from stdin and store it to the "+
"external configmaps storage indicated by the --target "+
"flag; if the --batch flag is used, instead of "+
"reading a single configmap entry from stdin, each command "+
"line argument is treated as a file and each file's "+
"content is added to the configmap with the file's name "+
"as the key name for the configmap entry",
x,
)
return err
}

func (x *storeConfigmapCommand) Execute(args []string) error {
var entries []*entry

switch {
case x.Batch && len(args) == 0:
return fmt.Errorf("at least one command line argument is " +
"required when using --batch flag")

case x.Batch:
for _, file := range args {
log("Reading value/entry from file %s", file)
content, err := readFile(file)
if err != nil {
return fmt.Errorf("cannot read file %s: %v",
file, err)
}

entries = append(entries, &entry{
key: filepath.Base(file),
value: content,
})
}

default:
log("Reading value/entry from stdin")
value, err := io.ReadAll(os.Stdin)
if err != nil {
return fmt.Errorf("error reading entry from stdin: %v", err)
}
entries = append(entries, &entry{value: string(value)})
}

switch x.Target {
case storageK8s:
// Take the actual entry key from the options if we aren't in
// batch mode.
if len(entries) == 1 && entries[0].key == "" {
entries[0].key = x.K8s.KeyName
}

return storeConfigmapsK8s(entries, x.K8s, x.Overwrite)

default:
return fmt.Errorf("invalid configmap storage target %s", x.Target)
}
}

func storeConfigmapsK8s(entries []*entry, opts *targetK8sConfigmap,
overwrite bool) error {

if opts.Name == "" {
return fmt.Errorf("configmap name is required")
}

for _, entry := range entries {
if entry.key == "" {
return fmt.Errorf("configmap entry key name is required")
}

entryOpts := &k8sObjectOptions{
Namespace: opts.Namespace,
Name: opts.Name,
KeyName: entry.key,
ObjectType: ObjectTypeConfigMap,
}

log("Storing key with name %s to configmap %s in namespace %s",
entryOpts.KeyName, entryOpts.Name,
entryOpts.Namespace)

err := saveK8s(entry.value, entryOpts, overwrite, opts.Helm)
if err != nil {
return fmt.Errorf("error storing key %s in configmap %s: "+
"%v", entry.key, opts.Name, err)
}
}

return nil
}
35 changes: 18 additions & 17 deletions cmd_store_secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,28 @@ import (
"github.com/jessevdk/go-flags"
)

type targetK8s struct {
type targetK8sSecret struct {
k8sSecretOptions

Helm *helmOptions `group:"Flags for configuring the Helm annotations (use when --target=k8s)" namespace:"helm"`
}

type secretEntry struct {
type entry struct {
key string
value string
}

type storeSecretCommand struct {
Batch bool `long:"batch" description:"Instead of reading one secret from stdin, read all files of the argument list and store them as entries in the secret"`
Overwrite bool `long:"overwrite" description:"Overwrite existing secret entries instead of aborting"`
Target string `long:"target" short:"t" description:"Secret storage target" choice:"k8s"`
K8s *targetK8s `group:"Flags for storing the secret as a value inside a Kubernetes Secret (use when --target=k8s)" namespace:"k8s"`
Batch bool `long:"batch" description:"Instead of reading one secret from stdin, read all files of the argument list and store them as entries in the secret"`
Overwrite bool `long:"overwrite" description:"Overwrite existing secret entries instead of aborting"`
Target string `long:"target" short:"t" description:"Secret storage target" choice:"k8s"`
K8s *targetK8sSecret `group:"Flags for storing the secret as a value inside a Kubernetes Secret (use when --target=k8s)" namespace:"k8s"`
}

func newStoreSecretCommand() *storeSecretCommand {
return &storeSecretCommand{
Target: storageK8s,
K8s: &targetK8s{
K8s: &targetK8sSecret{
k8sSecretOptions: k8sSecretOptions{
Namespace: defaultK8sNamespace,
},
Expand Down Expand Up @@ -59,7 +59,7 @@ func (x *storeSecretCommand) Register(parser *flags.Parser) error {
}

func (x *storeSecretCommand) Execute(args []string) error {
var entries []*secretEntry
var entries []*entry

switch {
case x.Batch && len(args) == 0:
Expand All @@ -75,7 +75,7 @@ func (x *storeSecretCommand) Execute(args []string) error {
file, err)
}

entries = append(entries, &secretEntry{
entries = append(entries, &entry{
key: filepath.Base(file),
value: content,
})
Expand All @@ -88,7 +88,7 @@ func (x *storeSecretCommand) Execute(args []string) error {
return fmt.Errorf("error reading secret from stdin: %v",
err)
}
entries = append(entries, &secretEntry{value: secret})
entries = append(entries, &entry{value: secret})
}

switch x.Target {
Expand All @@ -106,7 +106,7 @@ func (x *storeSecretCommand) Execute(args []string) error {
}
}

func storeSecretsK8s(entries []*secretEntry, opts *targetK8s,
func storeSecretsK8s(entries []*entry, opts *targetK8sSecret,
overwrite bool) error {

if opts.SecretName == "" {
Expand All @@ -118,15 +118,16 @@ func storeSecretsK8s(entries []*secretEntry, opts *targetK8s,
return fmt.Errorf("secret key name is required")
}

entryOpts := &k8sSecretOptions{
Namespace: opts.Namespace,
SecretName: opts.SecretName,
SecretKeyName: entry.key,
Base64: opts.Base64,
entryOpts := &k8sObjectOptions{
Namespace: opts.Namespace,
Name: opts.SecretName,
KeyName: entry.key,
Base64: opts.Base64,
ObjectType: ObjectTypeSecret,
}

log("Storing key with name %s to secret %s in namespace %s",
entryOpts.SecretKeyName, entryOpts.SecretName,
entryOpts.KeyName, entryOpts.Name,
entryOpts.Namespace)
err := saveK8s(entry.value, entryOpts, overwrite, opts.Helm)
if err != nil {
Expand Down
Loading

0 comments on commit 0238e58

Please sign in to comment.