github.com/openshift/installer@v1.4.17/pkg/asset/installconfig/openstack/openstack.go (about) 1 // Package openstack collects OpenStack-specific configuration. 2 package openstack 3 4 import ( 5 "context" 6 "fmt" 7 "sort" 8 "strings" 9 10 survey "github.com/AlecAivazis/survey/v2" 11 "github.com/AlecAivazis/survey/v2/core" 12 13 "github.com/openshift/installer/pkg/types/openstack" 14 ) 15 16 const ( 17 noExtNet = "<none>" 18 ) 19 20 // Platform collects OpenStack-specific configuration. 21 func Platform(ctx context.Context) (*openstack.Platform, error) { 22 cloudNames, err := getCloudNames() 23 if err != nil { 24 return nil, err 25 } 26 // Sort cloudNames so we can use sort.SearchStrings 27 sort.Strings(cloudNames) 28 var cloud string 29 err = survey.Ask([]*survey.Question{ 30 { 31 Prompt: &survey.Select{ 32 Message: "Cloud", 33 Help: "The OpenStack cloud name from clouds.yaml.", 34 Options: cloudNames, 35 }, 36 Validate: survey.ComposeValidators(survey.Required, func(ans interface{}) error { 37 value := ans.(core.OptionAnswer).Value 38 i := sort.SearchStrings(cloudNames, value) 39 if i == len(cloudNames) || cloudNames[i] != value { 40 return fmt.Errorf("invalid cloud name %q, should be one of %s", value, strings.Join(cloudNames, ", ")) 41 } 42 return nil 43 }), 44 }, 45 }, &cloud) 46 if err != nil { 47 return nil, fmt.Errorf("failed UserInput: %w", err) 48 } 49 50 networkNames, err := getExternalNetworkNames(ctx, cloud) 51 if err != nil { 52 return nil, err 53 } 54 networkNames = append(networkNames, noExtNet) 55 sort.Strings(networkNames) 56 var extNet string 57 err = survey.Ask([]*survey.Question{ 58 { 59 Prompt: &survey.Select{ 60 Message: "ExternalNetwork", 61 Help: "The OpenStack external network name to be used for installation.", 62 Options: networkNames, 63 Default: noExtNet, 64 }, 65 Validate: survey.ComposeValidators(survey.Required, func(ans interface{}) error { 66 value := ans.(core.OptionAnswer).Value 67 i := sort.SearchStrings(networkNames, value) 68 if i == len(networkNames) || networkNames[i] != value { 69 return fmt.Errorf("invalid network name %q, should be one of %s", value, strings.Join(networkNames, ", ")) 70 } 71 return nil 72 }), 73 }, 74 }, &extNet) 75 if extNet == noExtNet { 76 extNet = "" 77 } 78 if err != nil { 79 return nil, fmt.Errorf("failed UserInput: %w", err) 80 } 81 82 var apiFloatingIP string 83 if extNet != "" { 84 floatingIPs, err := getFloatingIPs(ctx, cloud, extNet) 85 if err != nil { 86 return nil, err 87 } 88 sort.Sort(floatingIPs) 89 err = survey.Ask([]*survey.Question{ 90 { 91 Prompt: &survey.Select{ 92 Message: "APIFloatingIPAddress", 93 Help: "The Floating IP address used for external access to the OpenShift API.", 94 Options: floatingIPs.Names(), 95 Description: func(_ string, index int) string { return floatingIPs.Description(index) }, 96 }, 97 Validate: survey.ComposeValidators(survey.Required, func(ans interface{}) error { 98 if value := ans.(core.OptionAnswer).Value; !floatingIPs.Contains(value) { 99 return fmt.Errorf("invalid floating IP %q, should be one of %s", value, strings.Join(floatingIPs.Names(), ", ")) 100 } 101 return nil 102 }), 103 }, 104 }, &apiFloatingIP) 105 if err != nil { 106 return nil, fmt.Errorf("failed UserInput: %w", err) 107 } 108 } 109 110 flavorNames, err := getFlavorNames(ctx, cloud) 111 if err != nil { 112 return nil, err 113 } 114 sort.Strings(flavorNames) 115 var flavor string 116 err = survey.Ask([]*survey.Question{ 117 { 118 Prompt: &survey.Select{ 119 Message: "FlavorName", 120 Help: "The OpenStack flavor to use for control-plane and compute nodes. A flavor with at least 16 GB RAM is recommended.", 121 Options: flavorNames, 122 }, 123 Validate: survey.ComposeValidators(survey.Required, func(ans interface{}) error { 124 value := ans.(core.OptionAnswer).Value 125 i := sort.SearchStrings(flavorNames, value) 126 if i == len(flavorNames) || flavorNames[i] != value { 127 return fmt.Errorf("invalid flavor name %q, should be one of %s", value, strings.Join(flavorNames, ", ")) 128 } 129 return nil 130 }), 131 }, 132 }, &flavor) 133 if err != nil { 134 return nil, fmt.Errorf("failed UserInput: %w", err) 135 } 136 137 return &openstack.Platform{ 138 APIFloatingIP: apiFloatingIP, 139 Cloud: cloud, 140 ExternalNetwork: extNet, 141 DefaultMachinePlatform: &openstack.MachinePool{ 142 FlavorName: flavor, 143 }, 144 }, nil 145 }