mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 01:40:07 +00:00
teach gce cloud to handle alpha/beta operations
This commit is contained in:
parent
6a644c25f8
commit
25f8c946f5
@ -88,6 +88,8 @@ go_test(
|
|||||||
"//pkg/cloudprovider:go_default_library",
|
"//pkg/cloudprovider:go_default_library",
|
||||||
"//pkg/kubelet/apis:go_default_library",
|
"//pkg/kubelet/apis:go_default_library",
|
||||||
"//vendor/golang.org/x/oauth2/google:go_default_library",
|
"//vendor/golang.org/x/oauth2/google:go_default_library",
|
||||||
|
"//vendor/google.golang.org/api/compute/v0.alpha:go_default_library",
|
||||||
|
"//vendor/google.golang.org/api/compute/v0.beta:go_default_library",
|
||||||
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
||||||
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
|
@ -80,6 +80,11 @@ const (
|
|||||||
gceComputeAPIEndpoint = "https://www.googleapis.com/compute/v1/"
|
gceComputeAPIEndpoint = "https://www.googleapis.com/compute/v1/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// gceObject is an abstraction of all GCE API object in go client
|
||||||
|
type gceObject interface {
|
||||||
|
MarshalJSON() ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
// GCECloud is an implementation of Interface, LoadBalancer and Instances for Google Compute Engine.
|
// GCECloud is an implementation of Interface, LoadBalancer and Instances for Google Compute Engine.
|
||||||
type GCECloud struct {
|
type GCECloud struct {
|
||||||
// ClusterID contains functionality for getting (and initializing) the ingress-uid. Call GCECloud.Initialize()
|
// ClusterID contains functionality for getting (and initializing) the ingress-uid. Call GCECloud.Initialize()
|
||||||
|
@ -17,17 +17,20 @@ limitations under the License.
|
|||||||
package gce
|
package gce
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
compute "google.golang.org/api/compute/v1"
|
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||||
|
computebeta "google.golang.org/api/compute/v0.beta"
|
||||||
|
computev1 "google.golang.org/api/compute/v1"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gce *GCECloud) waitForOp(op *compute.Operation, getOperation func(operationName string) (*compute.Operation, error), mc *metricContext) error {
|
func (gce *GCECloud) waitForOp(op *computev1.Operation, getOperation func(operationName string) (*computev1.Operation, error), mc *metricContext) error {
|
||||||
if op == nil {
|
if op == nil {
|
||||||
return mc.Observe(fmt.Errorf("operation must not be nil"))
|
return mc.Observe(fmt.Errorf("operation must not be nil"))
|
||||||
}
|
}
|
||||||
@ -72,11 +75,11 @@ func (gce *GCECloud) waitForOp(op *compute.Operation, getOperation func(operatio
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func opIsDone(op *compute.Operation) bool {
|
func opIsDone(op *computev1.Operation) bool {
|
||||||
return op != nil && op.Status == "DONE"
|
return op != nil && op.Status == "DONE"
|
||||||
}
|
}
|
||||||
|
|
||||||
func getErrorFromOp(op *compute.Operation) error {
|
func getErrorFromOp(op *computev1.Operation) error {
|
||||||
if op != nil && op.Error != nil && len(op.Error.Errors) > 0 {
|
if op != nil && op.Error != nil && len(op.Error.Errors) > 0 {
|
||||||
err := &googleapi.Error{
|
err := &googleapi.Error{
|
||||||
Code: int(op.HttpErrorStatusCode),
|
Code: int(op.HttpErrorStatusCode),
|
||||||
@ -89,20 +92,77 @@ func getErrorFromOp(op *compute.Operation) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gce *GCECloud) waitForGlobalOp(op *compute.Operation, mc *metricContext) error {
|
func (gce *GCECloud) waitForGlobalOp(op gceObject, mc *metricContext) error {
|
||||||
return gce.waitForOp(op, func(operationName string) (*compute.Operation, error) {
|
switch v := op.(type) {
|
||||||
return gce.service.GlobalOperations.Get(gce.projectID, operationName).Do()
|
case *computealpha.Operation:
|
||||||
}, mc)
|
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
op, err := gce.serviceAlpha.GlobalOperations.Get(gce.projectID, operationName).Do()
|
||||||
|
return convertToV1Operation(op), err
|
||||||
|
}, mc)
|
||||||
|
case *computebeta.Operation:
|
||||||
|
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
op, err := gce.serviceBeta.GlobalOperations.Get(gce.projectID, operationName).Do()
|
||||||
|
return convertToV1Operation(op), err
|
||||||
|
}, mc)
|
||||||
|
case *computev1.Operation:
|
||||||
|
return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
return gce.service.GlobalOperations.Get(gce.projectID, operationName).Do()
|
||||||
|
}, mc)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected type: %T", v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gce *GCECloud) waitForRegionOp(op *compute.Operation, region string, mc *metricContext) error {
|
func (gce *GCECloud) waitForRegionOp(op gceObject, region string, mc *metricContext) error {
|
||||||
return gce.waitForOp(op, func(operationName string) (*compute.Operation, error) {
|
switch v := op.(type) {
|
||||||
return gce.service.RegionOperations.Get(gce.projectID, region, operationName).Do()
|
case *computealpha.Operation:
|
||||||
}, mc)
|
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
op, err := gce.serviceAlpha.RegionOperations.Get(gce.projectID, region, operationName).Do()
|
||||||
|
return convertToV1Operation(op), err
|
||||||
|
}, mc)
|
||||||
|
case *computebeta.Operation:
|
||||||
|
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
op, err := gce.serviceBeta.RegionOperations.Get(gce.projectID, region, operationName).Do()
|
||||||
|
return convertToV1Operation(op), err
|
||||||
|
}, mc)
|
||||||
|
case *computev1.Operation:
|
||||||
|
return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
return gce.service.RegionOperations.Get(gce.projectID, region, operationName).Do()
|
||||||
|
}, mc)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected type: %T", v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gce *GCECloud) waitForZoneOp(op *compute.Operation, zone string, mc *metricContext) error {
|
func (gce *GCECloud) waitForZoneOp(op gceObject, zone string, mc *metricContext) error {
|
||||||
return gce.waitForOp(op, func(operationName string) (*compute.Operation, error) {
|
switch v := op.(type) {
|
||||||
return gce.service.ZoneOperations.Get(gce.projectID, zone, operationName).Do()
|
case *computealpha.Operation:
|
||||||
}, mc)
|
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
op, err := gce.serviceAlpha.ZoneOperations.Get(gce.projectID, zone, operationName).Do()
|
||||||
|
return convertToV1Operation(op), err
|
||||||
|
}, mc)
|
||||||
|
case *computebeta.Operation:
|
||||||
|
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
op, err := gce.serviceBeta.ZoneOperations.Get(gce.projectID, zone, operationName).Do()
|
||||||
|
return convertToV1Operation(op), err
|
||||||
|
}, mc)
|
||||||
|
case *computev1.Operation:
|
||||||
|
return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) {
|
||||||
|
return gce.service.ZoneOperations.Get(gce.projectID, zone, operationName).Do()
|
||||||
|
}, mc)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected type: %T", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToV1Operation(object gceObject) *computev1.Operation {
|
||||||
|
enc, err := object.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||||
|
}
|
||||||
|
var op computev1.Operation
|
||||||
|
if err := json.Unmarshal(enc, &op); err != nil {
|
||||||
|
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 operation: %v", object, err))
|
||||||
|
}
|
||||||
|
return &op
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,15 @@ limitations under the License.
|
|||||||
package gce
|
package gce
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||||
|
computebeta "google.golang.org/api/compute/v0.beta"
|
||||||
|
computev1 "google.golang.org/api/compute/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExtraKeyInConfig(t *testing.T) {
|
func TestExtraKeyInConfig(t *testing.T) {
|
||||||
@ -437,3 +442,53 @@ func TestGenerateCloudConfigs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConvertToV1Operation(t *testing.T) {
|
||||||
|
v1Op := getTestOperation()
|
||||||
|
enc, _ := v1Op.MarshalJSON()
|
||||||
|
var op interface{}
|
||||||
|
var alphaOp computealpha.Operation
|
||||||
|
var betaOp computebeta.Operation
|
||||||
|
|
||||||
|
if err := json.Unmarshal(enc, &alphaOp); err != nil {
|
||||||
|
t.Errorf("Failed to unmarshal operation: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(enc, &betaOp); err != nil {
|
||||||
|
t.Errorf("Failed to unmarshal operation: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
op = convertToV1Operation(&alphaOp)
|
||||||
|
if _, ok := op.(*computev1.Operation); ok {
|
||||||
|
if !reflect.DeepEqual(op, v1Op) {
|
||||||
|
t.Errorf("Failed to maintain consistency across conversion")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Expect output to be type v1 operation, but got %v", op)
|
||||||
|
}
|
||||||
|
|
||||||
|
op = convertToV1Operation(&betaOp)
|
||||||
|
if _, ok := op.(*computev1.Operation); ok {
|
||||||
|
if !reflect.DeepEqual(op, v1Op) {
|
||||||
|
t.Errorf("Failed to maintain consistency across conversion")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Errorf("Expect output to be type v1 operation, but got %v", op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestOperation() *computev1.Operation {
|
||||||
|
return &computev1.Operation{
|
||||||
|
Name: "test",
|
||||||
|
Description: "test",
|
||||||
|
Id: uint64(12345),
|
||||||
|
Error: &computev1.OperationError{
|
||||||
|
Errors: []*computev1.OperationErrorErrors{
|
||||||
|
{
|
||||||
|
Code: "555",
|
||||||
|
Message: "error",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user