Skip to content

Commit

Permalink
Merge pull request #117 from TheThingsNetwork/fix/env
Browse files Browse the repository at this point in the history
Fix update of flags from the environment
  • Loading branch information
KrishnaIyer authored Mar 13, 2024
2 parents 6283d81 + 72d0a60 commit 37b8acd
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 97 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Fixed

- Flags are always only loaded from the env. Now flags are loaded from env only if set.

## [v0.11.2] (2024-03-04)

### Fixed
Expand Down
29 changes: 14 additions & 15 deletions pkg/source/chirpstack/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,35 +57,35 @@ func New() *Config {

config.flags.StringVar(&config.url,
"api-url",
"",
os.Getenv("CHIRPSTACK_API_URL"),
"ChirpStack API URL")
config.flags.StringVar(&config.apiKey,
"api-key",
"",
"ChirpStack API key")
config.flags.StringVar(&config.caCertPath,
"ca-cert-path",
"",
os.Getenv("CHIRPSTACK_CA_CERT_PATH"),
"(optional) Path to the CA certificate file for ChirpStack API TLS connections")
config.flags.BoolVar(&config.insecure,
"insecure",
false,
os.Getenv("CHIRPSTACK_INSECURE") == "true",
"Do not connect to ChirpStack over TLS")
config.flags.BoolVar(&config.ExportVars,
"export-vars",
false,
os.Getenv("EXPORT_VARS") == "true",
"Export device variables from ChirpStack")
config.flags.BoolVar(&config.ExportSession,
"export-session",
false,
os.Getenv("EXPORT_SESSION") == "true",
"Export device session keys from ChirpStack")
config.flags.StringVar(&config.joinEUI,
"join-eui",
"",
os.Getenv("JOIN_EUI"),
"JoinEUI of exported devices")
config.flags.StringVar(&config.FrequencyPlanID,
"frequency-plan-id",
"",
os.Getenv("FREQUENCY_PLAN_ID"),
"Frequency Plan ID of exported devices")

return config
Expand All @@ -94,26 +94,25 @@ func New() *Config {
func (c *Config) Initialize(src source.Config) error {
c.src = src

if c.apiKey = os.Getenv("CHIRPSTACK_API_KEY"); c.apiKey == "" {
if apiKey := os.Getenv("CHIRPSTACK_API_KEY"); apiKey != "" && c.apiKey == "" {
c.apiKey = apiKey
}
if c.apiKey == "" {
return errNoAPIToken.New()
}
if c.url = os.Getenv("CHIRPSTACK_API_URL"); c.url == "" {
if c.url == "" {
return errNoAPIURL.New()
}
if c.FrequencyPlanID = os.Getenv("FREQUENCY_PLAN_ID"); c.FrequencyPlanID == "" {
if c.FrequencyPlanID == "" {
return errNoFrequencyPlan.New()
}
if c.joinEUI = os.Getenv("JOIN_EUI"); c.joinEUI == "" {
if c.joinEUI == "" {
return errNoJoinEUI.New()
}
c.JoinEUI = &types.EUI64{}
if err := c.JoinEUI.UnmarshalText([]byte(c.joinEUI)); err != nil {
return errInvalidJoinEUI.WithAttributes("join_eui", c.joinEUI)
}
c.caCertPath = os.Getenv("CHIRPSTACK_CA_CERT_PATH")
c.insecure = os.Getenv("CHIRPSTACK_INSECURE") == "true"
c.ExportSession = os.Getenv("EXPORT_SESSION") == "true"
c.ExportVars = os.Getenv("EXPORT_VARS") == "true"

err := c.dialGRPC(
grpc.FailOnNonTempDialError(true),
Expand Down
43 changes: 17 additions & 26 deletions pkg/source/firefly/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,36 +53,36 @@ func NewConfig() *Config {

config.flags.StringVar(&config.Host,
"host",
"",
os.Getenv("FIREFLY_HOST"),
"Host of the Firefly API. Don't use the scheme (http/https). Port is optional")
config.flags.StringVar(&config.CACertPath,
"ca-cert-path",
"",
os.Getenv("FIREFLY_CA_CERT_PATH"),
"(optional) Path to the CA certificate for the Firefly API")
config.flags.StringVar(&config.APIKey,
"api-key",
"",
"Key to access the Firefly API")
config.flags.StringVar(&config.joinEUI,
"join-eui",
"",
os.Getenv("JOIN_EUI"),
"JoinEUI for the exported devices")
config.flags.StringVar(&config.frequencyPlanID,
"frequency-plan-id",
"",
os.Getenv("FREQUENCY_PLAN_ID"),
"Frequency Plan ID for the exported devices")
config.flags.StringVar(&config.macVersion,
"mac-version",
"",
os.Getenv("MAC_VERSION"),
`LoRaWAN MAC version for the exported devices.
Supported options are 1.0.0, 1.0.1, 1.0.2a, 1.0.2b, 1.0.3, 1.1.0a, 1.1.0b`)
config.flags.StringVar(&config.appID,
"app-id",
"",
os.Getenv("APP_ID"),
"Application ID for the exported devices")
config.flags.BoolVar(&config.invalidateKeys,
"invalidate-keys",
false,
os.Getenv("INVALIDATE_KEYS") == "true",
`Invalidate the root and/or session keys of the devices on the Firefly server.
This is necessary to prevent both networks from communicating with the same device.
The last byte of the keys will be incremented by 0x01. This enables an easy rollback if necessary.
Expand All @@ -91,11 +91,11 @@ where the devices are exported but they are still valid on the firefly server
`)
config.flags.BoolVar(&config.UseHTTP,
"use-http",
false,
os.Getenv("FIREFLY_USE_HTTP") == "true",
"(optional) Use HTTP instead of HTTPS for the Firefly API. Only for testing")
config.flags.BoolVar(&config.all,
"all",
false,
os.Getenv("EXPORT_ALL") == "true",
"Export all devices that the API key has access to. This is only used by the application command")
return config
}
Expand All @@ -104,34 +104,25 @@ where the devices are exported but they are still valid on the firefly server
func (c *Config) Initialize(src source.Config) error {
c.src = src

if c.appID = os.Getenv("APP_ID"); c.appID == "" {
if apiKey := os.Getenv("FIREFLY_API_KEY"); apiKey != "" && c.APIKey == "" {
c.APIKey = apiKey
}
if c.appID == "" {
return errNoAppID.New()
}
if c.frequencyPlanID = os.Getenv("FREQUENCY_PLAN_ID"); c.frequencyPlanID == "" {
if c.frequencyPlanID == "" {
return errNoFrequencyPlanID.New()
}
if c.joinEUI = os.Getenv("JOIN_EUI"); c.joinEUI == "" {
if c.joinEUI == "" {
return errNoJoinEUI.New()
}
if invalidateKeys := os.Getenv("JOIN_EUI"); invalidateKeys == "true" {
c.invalidateKeys = true
}
if all := os.Getenv("ALL"); all == "true" {
c.all = true
}

if c.Host = os.Getenv("FIREFLY_HOST"); c.Host == "" {
if c.Host == "" {
return errNoHost.New()
}
if c.APIKey = os.Getenv("FIREFLY_API_KEY"); c.APIKey == "" {
if c.APIKey == "" {
return errNoAPIKey.New()
}
c.CACertPath = os.Getenv("FIREFLY_CA_CERT_PATH")
if useHTTP := os.Getenv("FIREFLY_USE_HTTP"); useHTTP == "true" {
c.UseHTTP = true
}

c.macVersion = os.Getenv("MAC_VERSION")
switch c.macVersion {
case "1.0.0":
c.derivedMacVersion = ttnpb.MACVersion_MAC_V1_0
Expand Down
62 changes: 39 additions & 23 deletions pkg/source/ttnv2/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,62 +35,62 @@ const (
clientName = "ttn-lw-migrate"
)

func New() (*Config, *pflag.FlagSet) {
var (
config = &Config{sdkConfig: ttnsdk.NewCommunityConfig(clientName)}
flags = &pflag.FlagSet{}
)
func NewConfig() *Config {
config := &Config{
sdkConfig: ttnsdk.NewCommunityConfig(clientName),
flags: &pflag.FlagSet{},
}

flags.StringVar(&config.frequencyPlanID,
config.flags.StringVar(&config.frequencyPlanID,
"frequency-plan-id",
os.Getenv("FREQUENCY_PLAN_ID"),
"Frequency Plan ID of exported devices")
flags.StringVar(&config.appID,
config.flags.StringVar(&config.appID,
"app-id",
os.Getenv("TTNV2_APP_ID"),
"TTN Application ID")
flags.StringVar(&config.appAccessKey,
config.flags.StringVar(&config.appAccessKey,
"app-access-key",
os.Getenv("TTNV2_APP_ACCESS_KEY"),
"",
"TTN Application Access Key (with 'devices' permissions")
flags.StringVar(&config.caCert,
config.flags.StringVar(&config.caCert,
"ca-cert",
os.Getenv("TTNV2_CA_CERT"),
"(only for private networks)")
flags.StringVar(&config.sdkConfig.HandlerAddress,
config.flags.StringVar(&config.sdkConfig.HandlerAddress,
"handler-address",
os.Getenv("TTNV2_HANDLER_ADDRESS"),
"(only for private networks) Address for the Handler")
flags.StringVar(&config.sdkConfig.AccountServerAddress,
config.flags.StringVar(&config.sdkConfig.AccountServerAddress,
"account-server-address",
os.Getenv("TTNV2_ACCOUNT_SERVER_ADDRESS"),
"(only for private networks) Address for the Account Server")
flags.StringVar(&config.sdkConfig.AccountServerClientID,
config.flags.StringVar(&config.sdkConfig.AccountServerClientID,
"account-server-client-id",
os.Getenv("TTNV2_ACCOUNT_SERVER_CLIENT_ID"),
"(only for private networks) Client ID for the Account Server")
flags.StringVar(&config.sdkConfig.AccountServerClientSecret,
config.flags.StringVar(&config.sdkConfig.AccountServerClientSecret,
"account-server-client-secret",
os.Getenv("TTNV2_ACCOUNT_SERVER_CLIENT_SECRET"),
"",
"(only for private networks) Client secret for the Account Server")
flags.StringVar(&config.sdkConfig.DiscoveryServerAddress,
config.flags.StringVar(&config.sdkConfig.DiscoveryServerAddress,
"discovery-server-address",
os.Getenv("TTNV2_DISCOVERY_SERVER_ADDRESS"),
"(only for private networks) Address for the Discovery Server")
flags.BoolVar(&config.sdkConfig.DiscoveryServerInsecure,
config.flags.BoolVar(&config.sdkConfig.DiscoveryServerInsecure,
"discovery-server-insecure",
false,
os.Getenv("TTNV2_DISCOVERY_SERVER_INSECURE") == "true",
"(only for private networks) Not recommended")
flags.BoolVar(&config.withSession,
config.flags.BoolVar(&config.withSession,
"with-session",
true,
os.Getenv("TTNV2_WITH_SESSION") == "true",
"Export device session keys and frame counters")
flags.BoolVar(&config.resetsToFrequencyPlan,
config.flags.BoolVar(&config.resetsToFrequencyPlan,
"resets-to-frequency-plan",
false,
os.Getenv("TTNV2_RESETS_TO_FREQUENCY_PLAN") == "true",
"Configure preset frequencies for ABP devices so that they match the used Frequency Plan")

return config, flags
return config
}

type Config struct {
Expand All @@ -106,10 +106,18 @@ type Config struct {
dryRun bool
resetsToFrequencyPlan bool

flags *pflag.FlagSet
fpStore *frequencyplans.Store
}

func (c *Config) Initialize(rootConfig source.Config) error {
if appAccessKey := os.Getenv("TTNV2_APP_ACCESS_KEY"); appAccessKey != "" && c.appAccessKey == "" {
c.appAccessKey = appAccessKey
}
if accountServerClientSecret := os.Getenv("TTNV2_ACCOUNT_SERVER_CLIENT_SECRET"); accountServerClientSecret != "" && c.sdkConfig.AccountServerClientSecret == "" {
c.sdkConfig.AccountServerClientSecret = accountServerClientSecret
}

if c.caCert != "" {
if c.sdkConfig.TLSConfig == nil {
c.sdkConfig.TLSConfig = new(tls.Config)
Expand All @@ -128,6 +136,9 @@ func (c *Config) Initialize(rootConfig source.Config) error {
rootCAs.AppendCertsFromPEM(pemBytes)
}

if c.appID == "" {
return errNoAppID.New()
}
if c.appAccessKey == "" {
return errNoAppAccessKey.New()
}
Expand Down Expand Up @@ -155,3 +166,8 @@ func (c *Config) Initialize(rootConfig source.Config) error {

return nil
}

// Flags returns the flags for the configuration.
func (c *Config) Flags() *pflag.FlagSet {
return c.flags
}
5 changes: 4 additions & 1 deletion pkg/source/ttnv2/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ func createNewSource(cfg *Config) source.CreateSource {

// NewSource creates a new TTNv2 Source.
func NewSource(ctx context.Context, cfg *Config, rootCfg source.Config) (source.Source, error) {
if err := cfg.Initialize(rootCfg); err != nil {
return nil, err
}
s := &Source{
ctx: ctx,
config: cfg,
Expand All @@ -60,7 +63,7 @@ func NewSource(ctx context.Context, cfg *Config, rootCfg source.Config) (source.
return nil, err
}
s.mgr = newDeviceManager(ctx, mgr)
return s, cfg.Initialize(rootCfg)
return s, nil
}

// ExportDevice implements the source.Source interface.
Expand Down
4 changes: 2 additions & 2 deletions pkg/source/ttnv2/ttnv2.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ package ttnv2
import "go.thethings.network/lorawan-stack-migrate/pkg/source"

func init() {
cfg, flags := New()
cfg := NewConfig()

source.RegisterSource(source.Registration{
Name: "ttnv2",
Description: "Migrate from The Things Network Stack V2",
FlagSet: flags,
FlagSet: cfg.Flags(),
Create: createNewSource(cfg),
})
}
Loading

0 comments on commit 37b8acd

Please sign in to comment.