Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 1 addition & 24 deletions cluster-autoscaler/cloudprovider/externalgrpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,7 @@ The `CloudProvider` interface was designed with the assumption that its implemen

### Code Generation

To regenerate the gRPC code:

1. install `protoc` and `protoc-gen-go-grpc`:

```bash
go install google.golang.org/protobuf/cmd/[email protected]
go install google.golang.org/grpc/cmd/[email protected]
```

2. import proto dependencies using go modules
```bash
go mod vendor
```

3. generate gRPC client and server code:

```bash
protoc \
-I ./cluster-autoscaler \
-I ./cluster-autoscaler/vendor \
--go_out=. \
--go-grpc_out=. \
./cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto
```
To regenerate the gRPC code, run the `cluster-autoscaler/hack/update-proto.sh` script

### General considerations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/anypb"

apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
Expand Down Expand Up @@ -123,8 +124,25 @@ func (w *Wrapper) PricingNodePrice(_ context.Context, req *protos.PricingNodePri
return nil, err
}
reqNode := req.GetNode()
reqStartTime := req.GetStartTime()
reqEndTime := req.GetEndTime()

var reqStartTime *metav1.Time
if startTimestamp := req.GetStartTimestamp(); startTimestamp != nil {
// read standard protobuf timestamp if set
reqStartTime = &metav1.Time{Time: startTimestamp.AsTime()}
} else {
// otherwise fallback to reading metav1.Time
reqStartTime = req.GetStartTime()
}

var reqEndTime *metav1.Time
if endTimestamp := req.GetEndTimestamp(); endTimestamp != nil {
// read standard protobuf timestamp if set
reqEndTime = &metav1.Time{Time: endTimestamp.AsTime()}
} else {
// otherwise fallback to reading metav1.Time
reqEndTime = req.GetEndTime()
}

if reqNode == nil || reqStartTime == nil || reqEndTime == nil {
return nil, fmt.Errorf("request fields were nil")
}
Expand All @@ -148,9 +166,38 @@ func (w *Wrapper) PricingPodPrice(_ context.Context, req *protos.PricingPodPrice
}
return nil, err
}
reqPod := req.GetPod()
reqStartTime := req.GetStartTime()
reqEndTime := req.GetEndTime()

var reqPod *apiv1.Pod
if podBytes := req.GetPodBytes(); podBytes != nil {
// decode from opaque bytes into pod if set
pod := &apiv1.Pod{}
if err := pod.Unmarshal(podBytes); err != nil {
return nil, err
}
reqPod = pod
} else {
// otherwise fallback to reading inlined pod
reqPod = req.GetPod()
}

var reqStartTime *metav1.Time
if startTimestamp := req.GetStartTimestamp(); startTimestamp != nil {
// read standard protobuf timestamp if set
reqStartTime = &metav1.Time{Time: startTimestamp.AsTime()}
} else {
// otherwise fallback to reading metav1.Time
reqStartTime = req.GetStartTime()
}

var reqEndTime *metav1.Time
if endTimestamp := req.GetEndTimestamp(); endTimestamp != nil {
// read standard protobuf timestamp if set
reqEndTime = &metav1.Time{Time: endTimestamp.AsTime()}
} else {
// otherwise fallback to reading metav1.Time
reqEndTime = req.GetEndTime()
}

if reqPod == nil || reqStartTime == nil || reqEndTime == nil {
return nil, fmt.Errorf("request fields were nil")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"

apiv1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -162,6 +164,9 @@ func (m *pricingModel) NodePrice(node *apiv1.Node, startTime time.Time, endTime
Node: externalGrpcNode(node),
StartTime: &start,
EndTime: &end,

StartTimestamp: timestamppb.New(startTime),
EndTimestamp: timestamppb.New(endTime),
})
if err != nil {
st, ok := status.FromError(err)
Expand All @@ -182,10 +187,20 @@ func (m *pricingModel) PodPrice(pod *apiv1.Pod, startTime time.Time, endTime tim
klog.V(5).Infof("Performing gRPC call PricingPodPrice for pod %v", pod.Name)
start := metav1.NewTime(startTime)
end := metav1.NewTime(endTime)

podBytes, err := pod.Marshal()
if err != nil {
return 0, err
}

res, err := m.client.PricingPodPrice(ctx, &protos.PricingPodPriceRequest{
Pod: pod,
StartTime: &start,
EndTime: &end,

PodBytes: podBytes,
StartTimestamp: timestamppb.New(startTime),
EndTimestamp: timestamppb.New(endTime),
})
if err != nil {
st, ok := status.FromError(err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/anypb"

apiv1 "k8s.io/api/core/v1"
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/externalgrpc/protos"
Expand Down Expand Up @@ -309,15 +310,17 @@ func TestCloudProvider_Pricing(t *testing.T) {
// test correct PodPrice call
m.On(
"PricingPodPrice", mock.Anything, mock.MatchedBy(func(req *protos.PricingPodPriceRequest) bool {
return req.Pod.Name == "pod1"
pod := &apiv1.Pod{}
return pod.Unmarshal(req.PodBytes) == nil && pod.Name == "pod1"
}),
).Return(
&protos.PricingPodPriceResponse{Price: 100},
nil,
)
m.On(
"PricingPodPrice", mock.Anything, mock.MatchedBy(func(req *protos.PricingPodPriceRequest) bool {
return req.Pod.Name == "pod2"
pod := &apiv1.Pod{}
return pod.Unmarshal(req.PodBytes) == nil && pod.Name == "pod2"
}),
).Return(
&protos.PricingPodPriceResponse{Price: 200},
Expand All @@ -341,7 +344,8 @@ func TestCloudProvider_Pricing(t *testing.T) {
// test grpc error for PodPrice
m.On(
"PricingPodPrice", mock.Anything, mock.MatchedBy(func(req *protos.PricingPodPriceRequest) bool {
return req.Pod.Name == "pod3"
pod := &apiv1.Pod{}
return pod.Unmarshal(req.PodBytes) == nil && pod.Name == "pod3"
}),
).Return(
&protos.PricingPodPriceResponse{},
Expand All @@ -357,7 +361,8 @@ func TestCloudProvider_Pricing(t *testing.T) {
// test notImplemented for PodPrice
m.On(
"PricingPodPrice", mock.Anything, mock.MatchedBy(func(req *protos.PricingPodPriceRequest) bool {
return req.Pod.Name == "pod4"
pod := &apiv1.Pod{}
return pod.Unmarshal(req.PodBytes) == nil && pod.Name == "pod4"
}),
).Return(
&protos.PricingPodPriceResponse{},
Expand Down
Loading
Loading