github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/openstack/config.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package openstack 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/juju/schema" 11 "github.com/juju/utils/v3" 12 "gopkg.in/juju/environschema.v1" 13 14 "github.com/juju/juju/environs/config" 15 ) 16 17 const ( 18 ExternalNetworkKey = "external-network" 19 NetworkKey = "network" 20 PolicyTargetGroupKey = "policy-target-group" 21 UseDefaultSecgroupKey = "use-default-secgroup" 22 UseOpenstackGBPKey = "use-openstack-gbp" 23 ) 24 25 var configSchema = environschema.Fields{ 26 UseDefaultSecgroupKey: { 27 Description: `Whether new machine instances should have the "default" Openstack security group assigned in addition to juju defined security groups.`, 28 Type: environschema.Tbool, 29 }, 30 NetworkKey: { 31 Description: "The network label or UUID to bring machines up on when multiple networks exist.", 32 Type: environschema.Tstring, 33 }, 34 ExternalNetworkKey: { 35 Description: "The network label or UUID to create floating IP addresses on when multiple external networks exist.", 36 Type: environschema.Tstring, 37 }, 38 UseOpenstackGBPKey: { 39 Description: "Whether to use Neutrons Group-Based Policy", 40 Type: environschema.Tbool, 41 }, 42 PolicyTargetGroupKey: { 43 Description: "The UUID of Policy Target Group to use for Policy Targets created.", 44 Type: environschema.Tstring, 45 }, 46 } 47 48 var configDefaults = schema.Defaults{ 49 UseDefaultSecgroupKey: false, 50 NetworkKey: "", 51 ExternalNetworkKey: "", 52 UseOpenstackGBPKey: false, 53 PolicyTargetGroupKey: "", 54 } 55 56 var configFields = func() schema.Fields { 57 fs, _, err := configSchema.ValidationSchema() 58 if err != nil { 59 panic(err) 60 } 61 return fs 62 }() 63 64 type environConfig struct { 65 *config.Config 66 attrs map[string]interface{} 67 } 68 69 func (c *environConfig) useDefaultSecurityGroup() bool { 70 return c.attrs[UseDefaultSecgroupKey].(bool) 71 } 72 73 func (c *environConfig) networks() []string { 74 raw := strings.Split(c.attrs[NetworkKey].(string), ",") 75 res := make([]string, len(raw)) 76 for i, net := range raw { 77 res[i] = strings.TrimSpace(net) 78 } 79 return res 80 } 81 82 func (c *environConfig) externalNetwork() string { 83 return c.attrs[ExternalNetworkKey].(string) 84 } 85 86 func (c *environConfig) useOpenstackGBP() bool { 87 return c.attrs[UseOpenstackGBPKey].(bool) 88 } 89 90 func (c *environConfig) policyTargetGroup() string { 91 return c.attrs[PolicyTargetGroupKey].(string) 92 } 93 94 type AuthMode string 95 96 // Schema returns the configuration schema for an environment. 97 func (EnvironProvider) Schema() environschema.Fields { 98 fields, err := config.Schema(configSchema) 99 if err != nil { 100 panic(err) 101 } 102 return fields 103 } 104 105 // ConfigSchema returns extra config attributes specific 106 // to this provider only. 107 func (p EnvironProvider) ConfigSchema() schema.Fields { 108 return configFields 109 } 110 111 // ConfigDefaults returns the default values for the 112 // provider specific config attributes. 113 func (p EnvironProvider) ConfigDefaults() schema.Defaults { 114 return configDefaults 115 } 116 117 func (p EnvironProvider) Validate(cfg, old *config.Config) (valid *config.Config, err error) { 118 // Check for valid changes for the base config values. 119 if err := config.Validate(cfg, old); err != nil { 120 return nil, err 121 } 122 123 validated, err := cfg.ValidateUnknownAttrs(configFields, p.Configurator.GetConfigDefaults()) 124 if err != nil { 125 return nil, err 126 } 127 ecfg := &environConfig{cfg, validated} 128 129 cfgAttrs := cfg.AllAttrs() 130 // If we have use-openstack-gbp set to Yes we require a proper UUID for policy-target-group. 131 hasPTG := false 132 if ptg := cfgAttrs[PolicyTargetGroupKey]; ptg != nil && ptg.(string) != "" { 133 if utils.IsValidUUIDString(ptg.(string)) { 134 hasPTG = true 135 } else { 136 return nil, fmt.Errorf("policy-target-group has invalid UUID: %q", ptg) 137 } 138 } 139 if useGBP := cfgAttrs[UseOpenstackGBPKey]; useGBP != nil && useGBP.(bool) == true { 140 if hasPTG == false { 141 return nil, fmt.Errorf("policy-target-group must be set when use-openstack-gbp is set") 142 } 143 if network := cfgAttrs[NetworkKey]; network != nil && network.(string) != "" { 144 return nil, fmt.Errorf("cannot use 'network' config setting when use-openstack-gbp is set") 145 } 146 } 147 148 // Check for deprecated fields and log a warning. We also print to stderr to ensure the user sees the message 149 // even if they are not running with --debug. 150 if defaultImageId := cfgAttrs["default-image-id"]; defaultImageId != nil && defaultImageId.(string) != "" { 151 msg := fmt.Sprintf( 152 "Config attribute %q (%v) is deprecated and ignored.\n"+ 153 "Your cloud provider should have set up image metadata to provide the correct image id\n"+ 154 "for your chosen series and architecture. If this is a private Openstack deployment without\n"+ 155 "existing image metadata, please run 'juju-metadata help' to see how suitable image"+ 156 "metadata can be generated.", 157 "default-image-id", defaultImageId) 158 logger.Warningf(msg) 159 } 160 if defaultInstanceType := cfgAttrs["default-instance-type"]; defaultInstanceType != nil && defaultInstanceType.(string) != "" { 161 msg := fmt.Sprintf( 162 "Config attribute %q (%v) is deprecated and ignored.\n"+ 163 "The correct instance flavor is determined using constraints, globally specified\n"+ 164 "when an model is bootstrapped, or individually when a charm is deployed.\n"+ 165 "See 'juju help bootstrap' or 'juju help deploy'.", 166 "default-instance-type", defaultInstanceType) 167 logger.Warningf(msg) 168 } 169 170 // Construct a new config with the ignored, deprecated attributes removed. 171 for _, attr := range []string{"default-image-id", "default-instance-type"} { 172 delete(cfgAttrs, attr) 173 delete(ecfg.attrs, attr) 174 } 175 for k, v := range ecfg.attrs { 176 cfgAttrs[k] = v 177 } 178 return config.New(config.NoDefaults, cfgAttrs) 179 }