Tim Windelschmidt | b6308cd | 2023-10-10 21:19:03 +0200 | [diff] [blame^] | 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | "flag" |
| 6 | "fmt" |
| 7 | "strings" |
| 8 | "time" |
| 9 | |
| 10 | "source.monogon.dev/cloud/equinix/wrapngo" |
| 11 | "source.monogon.dev/cloud/shepherd/manager" |
| 12 | ) |
| 13 | |
| 14 | var ( |
| 15 | NoSuchKey = errors.New("no such key") |
| 16 | ) |
| 17 | |
| 18 | // providerConfig contains configuration options used by both the Initializer and |
| 19 | // Provisioner components of the Shepherd. In CLI scenarios, RegisterFlags should |
| 20 | // be called to configure this struct from CLI flags. Otherwise, this structure |
| 21 | // should be explicitly configured, as the default values are not valid. |
| 22 | type providerConfig struct { |
| 23 | // ProjectId is the Equinix project UUID used by the manager. See Equinix API |
| 24 | // documentation for details. Must be set. |
| 25 | ProjectId string |
| 26 | |
| 27 | // KeyLabel specifies the ID to use when handling the Equinix-registered SSH |
| 28 | // key used to authenticate to newly created servers. Must be set. |
| 29 | KeyLabel string |
| 30 | |
| 31 | // DevicePrefix applied to all devices (machines) created by the Provisioner, |
| 32 | // and used by the Provisioner to identify machines which it managed. |
| 33 | // Must be set. |
| 34 | DevicePrefix string |
| 35 | |
| 36 | // OS defines the operating system new devices are created with. Its format |
| 37 | // is specified by Equinix API. |
| 38 | OS string |
| 39 | |
| 40 | // UseProjectKeys defines if the provisioner adds all ssh keys defined inside |
| 41 | // the used project to every new machine. This is only used for debug purposes. |
| 42 | UseProjectKeys bool |
| 43 | |
| 44 | // RebootWaitSeconds defines how many seconds to sleep after a reboot call |
| 45 | // to ensure a reboot actually happened. |
| 46 | RebootWaitSeconds int |
| 47 | |
| 48 | // ReservationCacheTimeout defines how after which time the reservations should be |
| 49 | // refreshed. |
| 50 | ReservationCacheTimeout time.Duration |
| 51 | } |
| 52 | |
| 53 | func (pc *providerConfig) check() error { |
| 54 | if pc.ProjectId == "" { |
| 55 | return fmt.Errorf("-equinix_project_id must be set") |
| 56 | } |
| 57 | if pc.KeyLabel == "" { |
| 58 | return fmt.Errorf("-equinix_ssh_key_label must be set") |
| 59 | } |
| 60 | if pc.DevicePrefix == "" { |
| 61 | return fmt.Errorf("-equinix_device_prefix must be set") |
| 62 | } |
| 63 | |
| 64 | // These variables are _very_ important to configure correctly, otherwise someone |
| 65 | // running this locally with prod creds will actually destroy production |
| 66 | // data. |
| 67 | if strings.Contains(pc.KeyLabel, "FIXME") { |
| 68 | return fmt.Errorf("refusing to run with -equinix_ssh_key_label %q, please set it to something unique", pc.KeyLabel) |
| 69 | } |
| 70 | if strings.Contains(pc.DevicePrefix, "FIXME") { |
| 71 | return fmt.Errorf("refusing to run with -equinix_device_prefix %q, please set it to something unique", pc.DevicePrefix) |
| 72 | } |
| 73 | |
| 74 | return nil |
| 75 | } |
| 76 | |
| 77 | func (pc *providerConfig) RegisterFlags() { |
| 78 | flag.StringVar(&pc.ProjectId, "equinix_project_id", "", "Equinix project ID where resources will be managed") |
| 79 | flag.StringVar(&pc.KeyLabel, "equinix_ssh_key_label", "shepherd-FIXME", "Label used to identify managed SSH key in Equinix project") |
| 80 | flag.StringVar(&pc.DevicePrefix, "equinix_device_prefix", "shepherd-FIXME-", "Prefix applied to all devices (machines) in Equinix project, used to identify managed machines") |
| 81 | flag.StringVar(&pc.OS, "equinix_os", "ubuntu_20_04", "OS that provisioner will deploy on Equinix machines. Not the target OS for cluster customers.") |
| 82 | flag.BoolVar(&pc.UseProjectKeys, "equinix_use_project_keys", false, "Add all Equinix project keys to newly provisioned machines, not just the provisioner's managed key. Debug/development only.") |
| 83 | flag.IntVar(&pc.RebootWaitSeconds, "equinix_reboot_wait_seconds", 30, "How many seconds to sleep to ensure a reboot happend") |
| 84 | flag.DurationVar(&pc.ReservationCacheTimeout, "equinix_reservation_cache_timeout", time.Minute*15, "Reservation cache validity timeo") |
| 85 | } |
| 86 | |
| 87 | func (pc *providerConfig) New(sshKey *manager.SSHKey, api wrapngo.Client) (*equinixProvider, error) { |
| 88 | if err := pc.check(); err != nil { |
| 89 | return nil, err |
| 90 | } |
| 91 | |
| 92 | return &equinixProvider{ |
| 93 | config: pc, |
| 94 | sshKey: sshKey, |
| 95 | api: api, |
| 96 | }, nil |
| 97 | } |