mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Merge pull request #88532 from zioproto/drop-network-tier-alpha-gate
Drop the alpha gating for Network Service Tier configuration support
This commit is contained in:
commit
3c159bb10f
@ -23,7 +23,6 @@ import (
|
|||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
|
||||||
computebeta "google.golang.org/api/compute/v0.beta"
|
computebeta "google.golang.org/api/compute/v0.beta"
|
||||||
compute "google.golang.org/api/compute/v1"
|
compute "google.golang.org/api/compute/v1"
|
||||||
|
|
||||||
@ -80,15 +79,6 @@ func (g *Cloud) ReserveRegionAddress(addr *compute.Address, region string) error
|
|||||||
return mc.Observe(g.c.Addresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr))
|
return mc.Observe(g.c.Addresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReserveAlphaRegionAddress creates an Alpha, regional address.
|
|
||||||
func (g *Cloud) ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error {
|
|
||||||
ctx, cancel := cloud.ContextWithCallTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
mc := newAddressMetricContext("reserve", region)
|
|
||||||
return mc.Observe(g.c.AlphaAddresses().Insert(ctx, meta.RegionalKey(addr.Name, region), addr))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReserveBetaRegionAddress creates a beta region address
|
// ReserveBetaRegionAddress creates a beta region address
|
||||||
func (g *Cloud) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error {
|
func (g *Cloud) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error {
|
||||||
ctx, cancel := cloud.ContextWithCallTimeout()
|
ctx, cancel := cloud.ContextWithCallTimeout()
|
||||||
@ -117,16 +107,6 @@ func (g *Cloud) GetRegionAddress(name, region string) (*compute.Address, error)
|
|||||||
return v, mc.Observe(err)
|
return v, mc.Observe(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAlphaRegionAddress returns the Alpha, regional address by name.
|
|
||||||
func (g *Cloud) GetAlphaRegionAddress(name, region string) (*computealpha.Address, error) {
|
|
||||||
ctx, cancel := cloud.ContextWithCallTimeout()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
mc := newAddressMetricContext("get", region)
|
|
||||||
v, err := g.c.AlphaAddresses().Get(ctx, meta.RegionalKey(name, region))
|
|
||||||
return v, mc.Observe(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBetaRegionAddress returns the beta region address by name
|
// GetBetaRegionAddress returns the beta region address by name
|
||||||
func (g *Cloud) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) {
|
func (g *Cloud) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) {
|
||||||
ctx, cancel := cloud.ContextWithCallTimeout()
|
ctx, cancel := cloud.ContextWithCallTimeout()
|
||||||
@ -185,14 +165,12 @@ func (g *Cloud) GetBetaRegionAddressByIP(region, ipAddress string) (*computebeta
|
|||||||
return nil, makeGoogleAPINotFoundError(fmt.Sprintf("Address with IP %q was not found in region %q", ipAddress, region))
|
return nil, makeGoogleAPINotFoundError(fmt.Sprintf("Address with IP %q was not found in region %q", ipAddress, region))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#51665): retire this function once Network Tiers becomes Beta in GCP.
|
|
||||||
func (g *Cloud) getNetworkTierFromAddress(name, region string) (string, error) {
|
func (g *Cloud) getNetworkTierFromAddress(name, region string) (string, error) {
|
||||||
if !g.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
|
||||||
return cloud.NetworkTierDefault.ToGCEValue(), nil
|
addr, err := g.GetRegionAddress(name, region)
|
||||||
}
|
|
||||||
addr, err := g.GetAlphaRegionAddress(name, region)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleAlphaNetworkTierGetError(err)
|
// Can't get the network tier, just return an error.
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
return addr.NetworkTier, nil
|
return addr.NetworkTier, nil
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,6 @@ limitations under the License.
|
|||||||
package gce
|
package gce
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// AlphaFeatureNetworkTiers allows Services backed by a GCP load balancer to choose
|
|
||||||
// what network tier to use. Currently supports "Standard" and "Premium" (default).
|
|
||||||
//
|
|
||||||
// alpha: v1.8 (for Services)
|
|
||||||
AlphaFeatureNetworkTiers = "NetworkTiers"
|
|
||||||
// AlphaFeatureILBSubsets allows InternalLoadBalancer services to include a subset
|
// AlphaFeatureILBSubsets allows InternalLoadBalancer services to include a subset
|
||||||
// of cluster nodes as backends instead of all nodes.
|
// of cluster nodes as backends instead of all nodes.
|
||||||
AlphaFeatureILBSubsets = "ILBSubsets"
|
AlphaFeatureILBSubsets = "ILBSubsets"
|
||||||
|
@ -182,14 +182,11 @@ func (g *Cloud) DeleteRegionForwardingRule(name, region string) error {
|
|||||||
return mc.Observe(g.c.ForwardingRules().Delete(ctx, meta.RegionalKey(name, region)))
|
return mc.Observe(g.c.ForwardingRules().Delete(ctx, meta.RegionalKey(name, region)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#51665): retire this function once Network Tiers becomes Beta in GCP.
|
|
||||||
func (g *Cloud) getNetworkTierFromForwardingRule(name, region string) (string, error) {
|
func (g *Cloud) getNetworkTierFromForwardingRule(name, region string) (string, error) {
|
||||||
if !g.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
fwdRule, err := g.GetRegionForwardingRule(name, region)
|
||||||
return cloud.NetworkTierDefault.ToGCEValue(), nil
|
|
||||||
}
|
|
||||||
fwdRule, err := g.GetAlphaRegionForwardingRule(name, region)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return handleAlphaNetworkTierGetError(err)
|
// Can't get the network tier, just return an error.
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
return fwdRule.NetworkTier, nil
|
return fwdRule.NetworkTier, nil
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ limitations under the License.
|
|||||||
package gce
|
package gce
|
||||||
|
|
||||||
import (
|
import (
|
||||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
|
||||||
computebeta "google.golang.org/api/compute/v0.beta"
|
computebeta "google.golang.org/api/compute/v0.beta"
|
||||||
compute "google.golang.org/api/compute/v1"
|
compute "google.golang.org/api/compute/v1"
|
||||||
)
|
)
|
||||||
@ -34,16 +33,11 @@ type CloudAddressService interface {
|
|||||||
DeleteRegionAddress(name, region string) error
|
DeleteRegionAddress(name, region string) error
|
||||||
// TODO: Mock Global endpoints
|
// TODO: Mock Global endpoints
|
||||||
|
|
||||||
// Alpha API.
|
|
||||||
GetAlphaRegionAddress(name, region string) (*computealpha.Address, error)
|
|
||||||
ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error
|
|
||||||
|
|
||||||
// Beta API
|
// Beta API
|
||||||
ReserveBetaRegionAddress(address *computebeta.Address, region string) error
|
ReserveBetaRegionAddress(address *computebeta.Address, region string) error
|
||||||
GetBetaRegionAddress(name string, region string) (*computebeta.Address, error)
|
GetBetaRegionAddress(name string, region string) (*computebeta.Address, error)
|
||||||
GetBetaRegionAddressByIP(region, ipAddress string) (*computebeta.Address, error)
|
GetBetaRegionAddressByIP(region, ipAddress string) (*computebeta.Address, error)
|
||||||
|
|
||||||
// TODO(#51665): Remove this once the Network Tiers becomes Alpha in GCP.
|
|
||||||
getNetworkTierFromAddress(name, region string) (string, error)
|
getNetworkTierFromAddress(name, region string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,10 +48,6 @@ type CloudForwardingRuleService interface {
|
|||||||
CreateRegionForwardingRule(rule *compute.ForwardingRule, region string) error
|
CreateRegionForwardingRule(rule *compute.ForwardingRule, region string) error
|
||||||
DeleteRegionForwardingRule(name, region string) error
|
DeleteRegionForwardingRule(name, region string) error
|
||||||
|
|
||||||
// Alpha API.
|
// Needed for the "Network Tiers" feature.
|
||||||
GetAlphaRegionForwardingRule(name, region string) (*computealpha.ForwardingRule, error)
|
|
||||||
CreateAlphaRegionForwardingRule(rule *computealpha.ForwardingRule, region string) error
|
|
||||||
|
|
||||||
// Needed for the Alpha "Network Tiers" feature.
|
|
||||||
getNetworkTierFromForwardingRule(name, region string) (string, error)
|
getNetworkTierFromForwardingRule(name, region string) (string, error)
|
||||||
}
|
}
|
||||||
|
@ -81,9 +81,7 @@ func (g *Cloud) ensureExternalLoadBalancer(clusterName string, clusterID string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
klog.V(4).Infof("ensureExternalLoadBalancer(%s): Desired network tier %q.", lbRefStr, netTier)
|
klog.V(4).Infof("ensureExternalLoadBalancer(%s): Desired network tier %q.", lbRefStr, netTier)
|
||||||
if g.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
g.deleteWrongNetworkTieredResources(loadBalancerName, lbRefStr, netTier)
|
||||||
g.deleteWrongNetworkTieredResources(loadBalancerName, lbRefStr, netTier)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the forwarding rule exists, and if so, what its IP is.
|
// Check if the forwarding rule exists, and if so, what its IP is.
|
||||||
fwdRuleExists, fwdRuleNeedsUpdate, fwdRuleIP, err := g.forwardingRuleNeedsUpdate(loadBalancerName, g.region, requestedIP, ports)
|
fwdRuleExists, fwdRuleNeedsUpdate, fwdRuleIP, err := g.forwardingRuleNeedsUpdate(loadBalancerName, g.region, requestedIP, ports)
|
||||||
@ -1072,9 +1070,6 @@ func ensureStaticIP(s CloudAddressService, name, serviceName, region, existingIP
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Cloud) getServiceNetworkTier(svc *v1.Service) (cloud.NetworkTier, error) {
|
func (g *Cloud) getServiceNetworkTier(svc *v1.Service) (cloud.NetworkTier, error) {
|
||||||
if !g.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
|
||||||
return cloud.NetworkTierDefault, nil
|
|
||||||
}
|
|
||||||
tier, err := GetServiceNetworkTier(svc)
|
tier, err := GetServiceNetworkTier(svc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Returns an error if the annotation is invalid.
|
// Returns an error if the annotation is invalid.
|
||||||
|
@ -233,9 +233,6 @@ func TestDeleteAddressWithWrongTier(t *testing.T) {
|
|||||||
s, err := fakeGCECloud(DefaultTestClusterValues())
|
s, err := fakeGCECloud(DefaultTestClusterValues())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Enable the cloud.NetworkTiers feature
|
|
||||||
s.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true
|
|
||||||
|
|
||||||
for desc, tc := range map[string]struct {
|
for desc, tc := range map[string]struct {
|
||||||
addrName string
|
addrName string
|
||||||
netTier cloud.NetworkTier
|
netTier cloud.NetworkTier
|
||||||
@ -401,8 +398,6 @@ func TestLoadBalancerWrongTierResourceDeletion(t *testing.T) {
|
|||||||
gce, err := fakeGCECloud(vals)
|
gce, err := fakeGCECloud(vals)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Enable the cloud.NetworkTiers feature
|
|
||||||
gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true
|
|
||||||
svc := fakeLoadbalancerService("")
|
svc := fakeLoadbalancerService("")
|
||||||
svc.Annotations = map[string]string{NetworkTierAnnotationKey: "Premium"}
|
svc.Annotations = map[string]string{NetworkTierAnnotationKey: "Premium"}
|
||||||
|
|
||||||
@ -460,8 +455,6 @@ func TestEnsureExternalLoadBalancerFailsIfInvalidNetworkTier(t *testing.T) {
|
|||||||
nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName)
|
nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Enable the cloud.NetworkTiers feature
|
|
||||||
gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true
|
|
||||||
svc := fakeLoadbalancerService("")
|
svc := fakeLoadbalancerService("")
|
||||||
svc.Annotations = map[string]string{NetworkTierAnnotationKey: wrongTier}
|
svc.Annotations = map[string]string{NetworkTierAnnotationKey: wrongTier}
|
||||||
|
|
||||||
@ -834,7 +827,6 @@ func TestDeleteWrongNetworkTieredResourcesSucceedsWhenNotFound(t *testing.T) {
|
|||||||
gce, err := fakeGCECloud(DefaultTestClusterValues())
|
gce, err := fakeGCECloud(DefaultTestClusterValues())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true
|
|
||||||
assert.Nil(t, gce.deleteWrongNetworkTieredResources("Wrong_LB_Name", "", cloud.NetworkTier("")))
|
assert.Nil(t, gce.deleteWrongNetworkTieredResources("Wrong_LB_Name", "", cloud.NetworkTier("")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,18 +281,6 @@ func makeGoogleAPINotFoundError(message string) error {
|
|||||||
return &googleapi.Error{Code: http.StatusNotFound, Message: message}
|
return &googleapi.Error{Code: http.StatusNotFound, Message: message}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#51665): Remove this once Network Tiers becomes Beta in GCP.
|
|
||||||
func handleAlphaNetworkTierGetError(err error) (string, error) {
|
|
||||||
if isForbidden(err) {
|
|
||||||
// Network tier is still an Alpha feature in GCP, and not every project
|
|
||||||
// is whitelisted to access the API. If we cannot access the API, just
|
|
||||||
// assume the tier is premium.
|
|
||||||
return cloud.NetworkTierDefault.ToGCEValue(), nil
|
|
||||||
}
|
|
||||||
// Can't get the network tier, just return an error.
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// containsCIDR returns true if outer contains inner.
|
// containsCIDR returns true if outer contains inner.
|
||||||
func containsCIDR(outer, inner *net.IPNet) bool {
|
func containsCIDR(outer, inner *net.IPNet) bool {
|
||||||
return outer.Contains(firstIPInRange(inner)) && outer.Contains(lastIPInRange(inner))
|
return outer.Contains(firstIPInRange(inner)) && outer.Contains(lastIPInRange(inner))
|
||||||
|
@ -88,7 +88,6 @@ go_library(
|
|||||||
"//vendor/github.com/miekg/dns:go_default_library",
|
"//vendor/github.com/miekg/dns:go_default_library",
|
||||||
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
"//vendor/github.com/onsi/ginkgo:go_default_library",
|
||||||
"//vendor/github.com/onsi/gomega:go_default_library",
|
"//vendor/github.com/onsi/gomega:go_default_library",
|
||||||
"//vendor/google.golang.org/api/compute/v0.alpha:go_default_library",
|
|
||||||
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
||||||
"//vendor/k8s.io/utils/net:go_default_library",
|
"//vendor/k8s.io/utils/net:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
compute "google.golang.org/api/compute/v1"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud"
|
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
@ -37,7 +37,7 @@ import (
|
|||||||
"github.com/onsi/ginkgo"
|
"github.com/onsi/ginkgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = SIGDescribe("Services [Feature:GCEAlphaFeature][Slow]", func() {
|
var _ = SIGDescribe("Services [Slow]", func() {
|
||||||
f := framework.NewDefaultFramework("services")
|
f := framework.NewDefaultFramework("services")
|
||||||
|
|
||||||
var cs clientset.Interface
|
var cs clientset.Interface
|
||||||
@ -109,7 +109,7 @@ var _ = SIGDescribe("Services [Feature:GCEAlphaFeature][Slow]", func() {
|
|||||||
requestedAddrName := fmt.Sprintf("e2e-ext-lb-net-tier-%s", framework.RunID)
|
requestedAddrName := fmt.Sprintf("e2e-ext-lb-net-tier-%s", framework.RunID)
|
||||||
gceCloud, err := gce.GetGCECloud()
|
gceCloud, err := gce.GetGCECloud()
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
requestedIP, err := reserveAlphaRegionalAddress(gceCloud, requestedAddrName, cloud.NetworkTierStandard)
|
requestedIP, err := reserveRegionalAddress(gceCloud, requestedAddrName, cloud.NetworkTierStandard)
|
||||||
framework.ExpectNoError(err, "failed to reserve a STANDARD tiered address")
|
framework.ExpectNoError(err, "failed to reserve a STANDARD tiered address")
|
||||||
defer func() {
|
defer func() {
|
||||||
if requestedAddrName != "" {
|
if requestedAddrName != "" {
|
||||||
@ -156,7 +156,7 @@ func waitAndVerifyLBWithTier(jig *e2eservice.TestJig, existingIP string, waitTim
|
|||||||
}
|
}
|
||||||
// If the IP has been used by previous test, sometimes we get the lingering
|
// If the IP has been used by previous test, sometimes we get the lingering
|
||||||
// 404 errors even after the LB is long gone. Tolerate and retry until the
|
// 404 errors even after the LB is long gone. Tolerate and retry until the
|
||||||
// the new LB is fully established since this feature is still Alpha in GCP.
|
// the new LB is fully established.
|
||||||
e2eservice.TestReachableHTTPWithRetriableErrorCodes(ingressIP, svcPort, []int{http.StatusNotFound}, checkTimeout)
|
e2eservice.TestReachableHTTPWithRetriableErrorCodes(ingressIP, svcPort, []int{http.StatusNotFound}, checkTimeout)
|
||||||
|
|
||||||
// Verify the network tier matches the desired.
|
// Verify the network tier matches the desired.
|
||||||
@ -170,7 +170,7 @@ func waitAndVerifyLBWithTier(jig *e2eservice.TestJig, existingIP string, waitTim
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getLBNetworkTierByIP(ip string) (cloud.NetworkTier, error) {
|
func getLBNetworkTierByIP(ip string) (cloud.NetworkTier, error) {
|
||||||
var rule *computealpha.ForwardingRule
|
var rule *compute.ForwardingRule
|
||||||
// Retry a few times to tolerate flakes.
|
// Retry a few times to tolerate flakes.
|
||||||
err := wait.PollImmediate(5*time.Second, 15*time.Second, func() (bool, error) {
|
err := wait.PollImmediate(5*time.Second, 15*time.Second, func() (bool, error) {
|
||||||
obj, err := getGCEForwardingRuleByIP(ip)
|
obj, err := getGCEForwardingRuleByIP(ip)
|
||||||
@ -186,12 +186,12 @@ func getLBNetworkTierByIP(ip string) (cloud.NetworkTier, error) {
|
|||||||
return cloud.NetworkTierGCEValueToType(rule.NetworkTier), nil
|
return cloud.NetworkTierGCEValueToType(rule.NetworkTier), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGCEForwardingRuleByIP(ip string) (*computealpha.ForwardingRule, error) {
|
func getGCEForwardingRuleByIP(ip string) (*compute.ForwardingRule, error) {
|
||||||
cloud, err := gce.GetGCECloud()
|
cloud, err := gce.GetGCECloud()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ruleList, err := cloud.ListAlphaRegionForwardingRules(cloud.Region())
|
ruleList, err := cloud.ListRegionForwardingRules(cloud.Region())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -220,14 +220,13 @@ func clearNetworkTier(svc *v1.Service) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add retries if this turns out to be flaky.
|
// TODO: add retries if this turns out to be flaky.
|
||||||
// TODO(#51665): remove this helper function once Network Tiers becomes beta.
|
func reserveRegionalAddress(cloud *gcecloud.Cloud, name string, netTier cloud.NetworkTier) (string, error) {
|
||||||
func reserveAlphaRegionalAddress(cloud *gcecloud.Cloud, name string, netTier cloud.NetworkTier) (string, error) {
|
Addr := &compute.Address{
|
||||||
alphaAddr := &computealpha.Address{
|
|
||||||
Name: name,
|
Name: name,
|
||||||
NetworkTier: netTier.ToGCEValue(),
|
NetworkTier: netTier.ToGCEValue(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cloud.ReserveAlphaRegionAddress(alphaAddr, cloud.Region()); err != nil {
|
if err := cloud.ReserveRegionAddress(Addr, cloud.Region()); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user