instance.go

77 lines
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
package scaffold

import (
	"fmt"
	"strings"

	"congo.gg/pkg/platform"
)

// FindInstance looks up an instance by name across all server types.
func FindInstance(cfg *InfraConfig, name string) (*Instance, string, error) {
	for serverType, instances := range cfg.Instances {
		for i := range instances {
			if instances[i].Name == name {
				return &instances[i], serverType, nil
			}
		}
	}

	names := AllInstanceNames(cfg)
	if len(names) == 0 {
		return nil, "", fmt.Errorf("no instances deployed. Use 'congo launch --new <server-type>' first")
	}
	return nil, "", fmt.Errorf("instance %q not found\nAvailable: %s", name, strings.Join(names, ", "))
}

// FindInstanceOrDefault returns the named instance, or the only instance if name is empty.
func FindInstanceOrDefault(cfg *InfraConfig, name string) (*Instance, error) {
	all := cfg.AllInstances()

	if name != "" {
		inst, _, err := FindInstance(cfg, name)
		return inst, err
	}

	if len(all) == 0 {
		return nil, fmt.Errorf("no instances deployed. Use 'congo launch --new <server-type>' first")
	}
	if len(all) == 1 {
		return &all[0], nil
	}

	return nil, &MultipleInstancesError{Instances: all}
}

// MultipleInstancesError is returned when an instance must be specified but multiple exist.
type MultipleInstancesError struct {
	Instances []Instance
}

func (e *MultipleInstancesError) Error() string {
	return fmt.Sprintf("multiple instances found, specify with --server: %s", strings.Join(AllNames(e.Instances), ", "))
}

// AllInstanceNames returns the names of all deployed instances.
func AllInstanceNames(cfg *InfraConfig) []string {
	return AllNames(cfg.AllInstances())
}

// AllNames returns names from a slice of instances.
func AllNames(instances []Instance) []string {
	names := make([]string, len(instances))
	for i, inst := range instances {
		names[i] = inst.Name
	}
	return names
}

// ToServer converts an Instance to a platform.Server for SSH operations.
func (inst *Instance) ToServer() *platform.Server {
	return &platform.Server{
		ID:     inst.ID,
		Name:   inst.Name,
		IP:     inst.IP,
		Region: inst.Region,
	}
}