From be901938a3589725d065023c577bbb8b8a0b65e5 Mon Sep 17 00:00:00 2001 From: Laszlo Kiraly Date: Fri, 11 Feb 2022 16:36:44 +0100 Subject: [PATCH] Use NSM_IPV6_PREFIX variable in case of IPv6 CIDR only (no IPv4) #12 Added LogLevel setting also. Signed-off-by: Laszlo Kiraly --- internal/pkg/config/config.go | 20 ++++----- main.go | 85 ++++++++++++++++++++++++++--------- 2 files changed, 74 insertions(+), 31 deletions(-) diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 6e54a57..c7f99fe 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -38,16 +38,16 @@ const ( // Config holds configuration parameters from environment variables type Config struct { - Name string `default:"vlan-server" desc:"Name of the endpoint"` - ConnectTo url.URL `default:"nsm-registry-svc:5002" desc:"url of registry service to connect to" split_words:"true"` - MaxTokenLifetime time.Duration `default:"24h" desc:"maximum lifetime of tokens" split_words:"true"` - CidrPrefix string `default:"169.254.0.0/16" desc:"CIDR Prefix to assign IPs from" split_words:"true"` - Ipv6Prefix string `default:"" desc:"Ipv6 Prefix for dual-stack" split_words:"true"` - RegisterService bool `default:"true" desc:"if true then registers network service on startup" split_words:"true"` - ListenOn url.URL `default:"tcp://:5003" desc:"tcp:// url to be listen on. It will be used as public to register NSM" split_words:"true"` - OpenTelemetryEndpoint string `default:"otel-collector.observability.svc.cluster.local:4317" desc:"OpenTelemetry Collector Endpoint"` - - Services []ServiceConfig `default:"" desc:"list of supported services"` + Name string `default:"vlan-server" desc:"Name of the endpoint"` + ConnectTo url.URL `default:"nsm-registry-svc:5002" desc:"url of registry service to connect to" split_words:"true"` + MaxTokenLifetime time.Duration `default:"24h" desc:"maximum lifetime of tokens" split_words:"true"` + CidrPrefix string `default:"169.254.0.0/16" desc:"IPv4 CIDR Prefix to assign IPs from" split_words:"true"` + Ipv6Prefix string `default:"" desc:"IPv6 CIDR Prefix to assign IPs from" split_words:"true"` + RegisterService bool `default:"true" desc:"if true then registers network service on startup" split_words:"true"` + ListenOn url.URL `default:"tcp://:5003" desc:"tcp:// url to be listen on. It will be used as public to register NSM" split_words:"true"` + OpenTelemetryEndpoint string `default:"otel-collector.observability.svc.cluster.local:4317" desc:"OpenTelemetry Collector Endpoint"` + LogLevel string `default:"INFO" desc:"Log level" split_words:"true"` + Services []ServiceConfig `default:"" desc:"list of supported services"` } // Process prints and processes env to config diff --git a/main.go b/main.go index c96025c..332fd99 100644 --- a/main.go +++ b/main.go @@ -26,10 +26,14 @@ import ( "net" "net/url" "os" + "os/signal" + "strings" + "syscall" "time" nested "github.com/antonfisher/nested-logrus-formatter" "github.com/edwarnicke/grpcfd" + "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig" "github.com/spiffe/go-spiffe/v2/workloadapi" @@ -66,8 +70,15 @@ func main() { // ******************************************************************************** // setup context to catch signals // ******************************************************************************** - ctx := context.Background() - ctx, cancel := context.WithCancel(ctx) + ctx, cancel := signal.NotifyContext( + context.Background(), + os.Interrupt, + // More Linux signals here + syscall.SIGHUP, + syscall.SIGTERM, + syscall.SIGQUIT, + ) + defer cancel() // ******************************************************************************** // setup logging @@ -100,8 +111,13 @@ func main() { if err := cfg.Process(); err != nil { logrus.Fatal(err.Error()) } + l, err := logrus.ParseLevel(cfg.LogLevel) + if err != nil { + logrus.Fatalf("invalid log level %s", cfg.LogLevel) + } + logrus.SetLevel(l) - log.FromContext(ctx).Infof("Config: %#v", cfg) + logger.Infof("Config: %#v", cfg) // ******************************************************************************** // Configure Open Telemetry @@ -112,8 +128,8 @@ func main() { metricExporter := opentelemetry.InitMetricExporter(ctx, collectorAddress) o := opentelemetry.Init(ctx, spanExporter, metricExporter, cfg.Name) defer func() { - if err := o.Close(); err != nil { - log.FromContext(ctx).Error(err.Error()) + if errClose := o.Close(); errClose != nil { + log.FromContext(ctx).Error(errClose.Error()) } }() } @@ -135,25 +151,12 @@ func main() { log.FromContext(ctx).Infof("executing phase 3: parsing network prefixes for ipam") // ******************************************************************************** - _, ipNet1, err := net.ParseCIDR(cfg.CidrPrefix) + ipamChain, err := getIPAMChain(cfg.CidrPrefix, cfg.Ipv6Prefix) if err != nil { - logrus.Fatalf("Could not parse cidr %s; %+v", cfg.CidrPrefix, err) + logger.Fatalf("error parsing CIDR from config: %v", err.Error()) } + log.FromContext(ctx).Infof("network prefixes parsed successfully") - var ipamChain networkservice.NetworkServiceServer - - if cfg.Ipv6Prefix != "" { - _, ipNet2, parseErr := net.ParseCIDR(cfg.Ipv6Prefix) - if parseErr != nil { - log.FromContext(ctx).Fatalf("error parsing cidr: %+v", err) - } - ipamChain = chain.NewNetworkServiceServer( - singlepointipam.NewServer(ipNet1), - singlepointipam.NewServer(ipNet2), - ) - } else { - ipamChain = chain.NewNetworkServiceServer(singlepointipam.NewServer(ipNet1)) - } // ******************************************************************************** logger.Infof("executing phase 4: create network service endpoint") // ******************************************************************************** @@ -306,3 +309,43 @@ func getNseEndpoint(listenOn *url.URL, cfg *config.Config) *registryapi.NetworkS } return nse } + +func getIPAMChain(ip4CIDR, ip6CIDR string) (networkservice.NetworkServiceServer, error) { + var ipNet1 *net.IPNet + var ipNet2 *net.IPNet + + if ip4CIDR != "" { + var parseErr error + _, ipNet1, parseErr = net.ParseCIDR(ip4CIDR) + if parseErr != nil { + logrus.Fatalf("Could not parse IPv4 CIDR %s; %+v", ip4CIDR, parseErr) + } + if strings.Contains(ip4CIDR, ":") { + return nil, errors.New("not ipv4 address is set") + } + } + if ip6CIDR != "" { + var parseErr error + _, ipNet2, parseErr = net.ParseCIDR(ip6CIDR) + if parseErr != nil { + logrus.Fatalf("Could not parse IPv6 CIDR: %s; %+v", ip6CIDR, parseErr) + } + if !strings.Contains(ip6CIDR, ":") { + return nil, errors.New("not ipv6 address is set") + } + } + + switch { + case ipNet1 != nil && ipNet2 != nil: + return chain.NewNetworkServiceServer( + singlepointipam.NewServer(ipNet1), + singlepointipam.NewServer(ipNet2), + ), nil + case ipNet2 != nil: + return chain.NewNetworkServiceServer(singlepointipam.NewServer(ipNet2)), nil + case ipNet1 != nil: + return chain.NewNetworkServiceServer(singlepointipam.NewServer(ipNet1)), nil + default: + return nil, errors.New("can not set CIDR") + } +}