github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/operator/orbiter/kinds/providers/static/desired.go (about)

     1  package static
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net"
     7  	"regexp"
     8  
     9  	"github.com/caos/orbos/mntr"
    10  	"github.com/caos/orbos/pkg/secret"
    11  	"github.com/caos/orbos/pkg/tree"
    12  )
    13  
    14  type DesiredV0 struct {
    15  	Common        *tree.Common `yaml:",inline"`
    16  	Spec          Spec
    17  	Loadbalancing *tree.Tree
    18  }
    19  
    20  type Spec struct {
    21  	Verbose             bool
    22  	Pools               map[string][]*Machine
    23  	Keys                *Keys
    24  	ExternalInterfaces  []string
    25  	PrivateInterface    string
    26  	LeaveOSRepositories bool
    27  }
    28  
    29  type Keys struct {
    30  	BootstrapKeyPrivate   *secret.Secret `yaml:",omitempty"`
    31  	BootstrapKeyPublic    *secret.Secret `yaml:",omitempty"`
    32  	MaintenanceKeyPrivate *secret.Secret `yaml:",omitempty"`
    33  	MaintenanceKeyPublic  *secret.Secret `yaml:",omitempty"`
    34  }
    35  
    36  func (d DesiredV0) validateAdapt() (err error) {
    37  	defer func() {
    38  		err = mntr.ToUserError(err)
    39  	}()
    40  
    41  	for pool, machines := range d.Spec.Pools {
    42  		for _, machine := range machines {
    43  			if err := machine.validate(); err != nil {
    44  				return fmt.Errorf("validating machine %s in pool %s failed: %w", machine.ID, pool, err)
    45  			}
    46  		}
    47  	}
    48  	return nil
    49  }
    50  
    51  func (d DesiredV0) validateQuery() (err error) {
    52  	defer func() {
    53  		err = mntr.ToUserError(err)
    54  	}()
    55  
    56  	if d.Spec.Keys == nil ||
    57  		d.Spec.Keys.BootstrapKeyPrivate == nil ||
    58  		d.Spec.Keys.BootstrapKeyPrivate.Value == "" {
    59  		return errors.New("bootstrap private ssh key missing... please provide a private ssh bootstrap key using orbctl writesecret command")
    60  	}
    61  
    62  	if d.Spec.Keys.MaintenanceKeyPrivate == nil ||
    63  		d.Spec.Keys.MaintenanceKeyPrivate.Value == "" ||
    64  		d.Spec.Keys.MaintenanceKeyPublic == nil ||
    65  		d.Spec.Keys.MaintenanceKeyPublic.Value == "" {
    66  		return errors.New("maintenance ssh key missing... please initialize your orb using orbctl configure command")
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func parseDesiredV0(desiredTree *tree.Tree) (desiredKind *DesiredV0, err error) {
    73  	defer func() {
    74  		err = mntr.ToUserError(err)
    75  	}()
    76  
    77  	desiredKind = &DesiredV0{
    78  		Common: desiredTree.Common,
    79  		Spec:   Spec{},
    80  	}
    81  
    82  	if err := desiredTree.Original.Decode(desiredKind); err != nil {
    83  		return nil, fmt.Errorf("parsing desired state failed: %w", err)
    84  	}
    85  
    86  	return desiredKind, nil
    87  }
    88  
    89  type Machine struct {
    90  	ID                  string
    91  	Hostname            string
    92  	IP                  string
    93  	RebootRequired      bool
    94  	ReplacementRequired bool
    95  }
    96  
    97  var internetHosts = regexp.MustCompile("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$")
    98  
    99  func validateName(name string) (err error) {
   100  	defer func() {
   101  		err = mntr.ToUserError(err)
   102  	}()
   103  
   104  	if len(name) > 63 || !internetHosts.MatchString(name) {
   105  		return fmt.Errorf("name must be compatible with https://tools.ietf.org/html/rfc1123#section-2, but %s is not", name)
   106  	}
   107  	return nil
   108  }
   109  
   110  func (c *Machine) validate() error {
   111  
   112  	if err := validateName(c.ID); err != nil {
   113  		return fmt.Errorf("validating id failed: %w", err)
   114  	}
   115  
   116  	if err := validateName(c.Hostname); err != nil {
   117  		return fmt.Errorf("validating hostname failed: %w", err)
   118  	}
   119  
   120  	if net.ParseIP(c.IP) == nil {
   121  		return fmt.Errorf("%s is not a valid ip address", c.IP)
   122  	}
   123  	return nil
   124  }