github.com/webmeshproj/webmesh-cni@v0.0.27/internal/config/config.go (about)

     1  /*
     2  Copyright 2023 Avi Zimmerman <avi.zimmerman@gmail.com>.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package config
    18  
    19  import (
    20  	"fmt"
    21  	"net/netip"
    22  	"time"
    23  
    24  	"github.com/spf13/pflag"
    25  
    26  	"github.com/webmeshproj/webmesh-cni/internal/host"
    27  	"github.com/webmeshproj/webmesh-cni/internal/metadata"
    28  )
    29  
    30  // Config is the configuration for the the webmesh-cni controllers.
    31  type Config struct {
    32  	// Manager is the configuration for the controller manager.
    33  	Manager ManagerConfig `koanf:"manager"`
    34  	// Storage is the configuration for the storage provider.
    35  	Storage StorageConfig `koanf:"storage"`
    36  	// Host is the configuration for the host webmesh node.
    37  	Host host.Config `koanf:"host"`
    38  }
    39  
    40  // ManagerConfig is the configuration for the controller manager.
    41  type ManagerConfig struct {
    42  	// RemoteEndpointDetection enables remote endpoint detection for peer containers.
    43  	RemoteEndpointDetection bool `koanf:"remote-endpoint-detection"`
    44  	// MetricsAddress is the address to bind the metrics server to.
    45  	MetricsAddress string `koanf:"metrics-address"`
    46  	// ProbeAddress is the address to bind the health probe server to.
    47  	ProbeAddress string `koanf:"probe-address"`
    48  	// ReconcileTimeout is the timeout for reconciling a container's interface.
    49  	ReconcileTimeout time.Duration `koanf:"reconcile-timeout"`
    50  	// MaxConcurrentReconciles is the maximum number of concurrent reconciles.
    51  	// Most of the reconcilers take exclusive locks, so this will only apply
    52  	// to reconcilers as a whole.
    53  	MaxConcurrentReconciles int `koanf:"max-concurrent-reconciles"`
    54  	// ShutdownTimeout is the timeout for shutting down the node.
    55  	ShutdownTimeout time.Duration `koanf:"shutdown-timeout"`
    56  	// ClusterDNSSelector is the selector used for trying to find pods that provide DNS
    57  	// for the cluster.
    58  	ClusterDNSSelector map[string]string `koanf:"cluster-dns-selector,omitempty"`
    59  	// ClusterDNSNamespace is the namespace to search for cluster DNS pods.
    60  	ClusterDNSNamespace string `koanf:"cluster-dns-namespace,omitempty"`
    61  	// ClusterDNSPortSelector is the name of the port assumed to be the DNS port.
    62  	ClusterDNSPortSelector string `koanf:"cluster-dns-port-selector,omitempty"`
    63  	// EnableMetadataServer enables a metadata server on the node that containers
    64  	// can use to query information about themselves.
    65  	EnableMetadataServer bool `koanf:"enable-metadata-server"`
    66  	// MetadataAddress is the address to bind the metadata server to.
    67  	MetadataAddress string `koanf:"metadata-address"`
    68  	// EnableMetadataIDTokens enables ID token endpoints on the metadata server
    69  	// for helping facilitate authentication between containers.
    70  	EnableMetadataIDTokens bool `koanf:"enable-metadata-id-tokens"`
    71  }
    72  
    73  // StorageConfig is the configuration for the storage provider.
    74  type StorageConfig struct {
    75  	// LeaderElectionLeaseDuration is the duration that non-leader candidates
    76  	// will wait to force acquire leadership.
    77  	LeaderElectLeaseDuration time.Duration `koanf:"leader-elect-lease-duration"`
    78  	// LeaderElectRenewDeadline is the duration that the acting master will retry
    79  	// refreshing leadership before giving up.
    80  	LeaderElectRenewDeadline time.Duration `koanf:"leader-elect-renew-deadline"`
    81  	// LeaderElectRetryPeriod is the duration the LeaderElector clients should wait
    82  	// between tries of actions.
    83  	LeaderElectRetryPeriod time.Duration `koanf:"leader-elect-retry-period"`
    84  	// CacheSyncTimeout is the amount of time to wait for the client cache to sync
    85  	// before starting the controller.
    86  	CacheSyncTimeout time.Duration `koanf:"cache-sync-timeout"`
    87  }
    88  
    89  // NewDefaultConfig returns a new default configuration for the webmesh-cni controllers.
    90  func NewDefaultConfig() Config {
    91  	return Config{
    92  		Manager: ManagerConfig{
    93  			RemoteEndpointDetection: false,
    94  			MetricsAddress:          ":8080",
    95  			ProbeAddress:            ":8081",
    96  			ReconcileTimeout:        15 * time.Second,
    97  			ShutdownTimeout:         30 * time.Second,
    98  			MaxConcurrentReconciles: 1,
    99  			ClusterDNSSelector: map[string]string{
   100  				"k8s-app": "kube-dns",
   101  			},
   102  			ClusterDNSNamespace:    "kube-system",
   103  			ClusterDNSPortSelector: "dns",
   104  			EnableMetadataServer:   true,
   105  			MetadataAddress:        metadata.DefaultServerAddress.String(),
   106  			EnableMetadataIDTokens: false,
   107  		},
   108  		Storage: StorageConfig{
   109  			LeaderElectLeaseDuration: 15 * time.Second,
   110  			LeaderElectRenewDeadline: 10 * time.Second,
   111  			LeaderElectRetryPeriod:   2 * time.Second,
   112  			CacheSyncTimeout:         10 * time.Second,
   113  		},
   114  		Host: host.NewDefaultConfig(),
   115  	}
   116  }
   117  
   118  func (c *Config) BindFlags(fs *pflag.FlagSet) {
   119  	c.Manager.BindFlags("manager.", fs)
   120  	c.Storage.BindFlags("storage.", fs)
   121  	c.Host.BindFlags("host.", fs)
   122  }
   123  
   124  func (c *ManagerConfig) BindFlags(prefix string, fs *pflag.FlagSet) {
   125  	fs.BoolVar(&c.RemoteEndpointDetection, prefix+"remote-endpoint-detection", c.RemoteEndpointDetection, "Enable remote endpoint detection for peer containers.")
   126  	fs.DurationVar(&c.ReconcileTimeout, prefix+"reconcile-timeout", c.ReconcileTimeout, "The timeout for reconciling a container's interface.")
   127  	fs.StringVar(&c.MetricsAddress, prefix+"metrics-address", c.MetricsAddress, "The address the metric endpoint binds to.")
   128  	fs.StringVar(&c.ProbeAddress, prefix+"probe-address", c.ProbeAddress, "The address the probe endpoint binds to.")
   129  	fs.DurationVar(&c.ShutdownTimeout, prefix+"shutdown-timeout", c.ShutdownTimeout, "The timeout for shutting down the node.")
   130  	fs.IntVar(&c.MaxConcurrentReconciles, prefix+"max-concurrent-reconciles", c.MaxConcurrentReconciles, "The maximum number of concurrent reconciles.")
   131  	fs.StringToStringVar(&c.ClusterDNSSelector, prefix+"cluster-dns-selector", c.ClusterDNSSelector, "The selector used for trying to find pods that provide DNS for the cluster")
   132  	fs.StringVar(&c.ClusterDNSNamespace, prefix+"cluster-dns-namespace", c.ClusterDNSNamespace, "The namespace to search for cluster DNS pods")
   133  	fs.StringVar(&c.ClusterDNSPortSelector, prefix+"cluster-dns-port-selector", c.ClusterDNSPortSelector, "The name of the port assumed to be the DNS port")
   134  	fs.BoolVar(&c.EnableMetadataServer, prefix+"enable-metadata-server", c.EnableMetadataServer, "Enable a metadata server on the node that containers can use to query information about themselves.")
   135  	fs.StringVar(&c.MetadataAddress, prefix+"metadata-address", c.MetadataAddress, "The address the metadata server binds to.")
   136  	fs.BoolVar(&c.EnableMetadataIDTokens, prefix+"enable-metadata-id-tokens", c.EnableMetadataIDTokens, "Enable ID token endpoints on the metadata server for helping facilitate authentication between containers.")
   137  }
   138  
   139  func (c *StorageConfig) BindFlags(prefix string, fs *pflag.FlagSet) {
   140  	fs.DurationVar(&c.LeaderElectLeaseDuration, prefix+"leader-elect-lease-duration", c.LeaderElectLeaseDuration, "The duration that non-leader candidates will wait to force acquire leadership.")
   141  	fs.DurationVar(&c.LeaderElectRenewDeadline, prefix+"leader-elect-renew-deadline", c.LeaderElectRenewDeadline, "The duration that the acting master will retry refreshing leadership before giving up.")
   142  	fs.DurationVar(&c.LeaderElectRetryPeriod, prefix+"leader-elect-retry-period", c.LeaderElectRetryPeriod, "The duration the LeaderElector clients should wait between tries of actions.")
   143  	fs.DurationVar(&c.CacheSyncTimeout, prefix+"cache-sync-timeout", c.CacheSyncTimeout, "The amount of time to wait for the client cache to sync before starting the controller.")
   144  }
   145  
   146  func (c *Config) Validate() error {
   147  	if err := c.Manager.Validate(); err != nil {
   148  		return fmt.Errorf("manager config: %w", err)
   149  	}
   150  	if err := c.Host.Validate(); err != nil {
   151  		return fmt.Errorf("network config: %w", err)
   152  	}
   153  	return nil
   154  }
   155  
   156  func (c *ManagerConfig) Validate() error {
   157  	if c.ReconcileTimeout <= 0 {
   158  		return fmt.Errorf("reconcile timeout must be positive")
   159  	}
   160  	if c.EnableMetadataServer {
   161  		_, err := netip.ParseAddrPort(c.MetadataAddress)
   162  		if err != nil {
   163  			return fmt.Errorf("invalid metadata address: %w", err)
   164  		}
   165  	}
   166  	return nil
   167  }