Skip to content

Commit

Permalink
More refactoring. Framework for external driver client. Unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
i344628 committed Jun 6, 2018
1 parent f7b3bdd commit 07f83a0
Show file tree
Hide file tree
Showing 7 changed files with 524 additions and 89 deletions.
53 changes: 52 additions & 1 deletion hack/fakegrpcserver/fakegrpcserver.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,60 @@
package main

import (
"log"
"path"
"time"

svr "github.com/gardener/machine-controller-manager/pkg/grpc/infraserver"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/testdata"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var (
tls = false //"Connection uses TLS if true, else plain TCP"
certFile = "" //"The TLS cert file"
keyFile = "" //"The TLS key file"
port = 10000 //"The server port"
)

func main() {
svr.StartServer()
server := &svr.ExternalDriverManager{
Port: port,
UseTLS: tls,
}
if tls {
if certFile == "" {
certFile = testdata.Path("server1.pem")
}
if keyFile == "" {
keyFile = testdata.Path("server1.key")
}
creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)
if err != nil {
log.Fatalf("Failed to generate credentials %v", err)
}
server.Options = []grpc.ServerOption{grpc.Creds(creds)}
}

server.Start()

// Test go routine to test end to end flow
go func() {
for {
driver, _ := server.GetDriver(metav1.TypeMeta{
Kind: "driver",
APIVersion: path.Join("poc", "alpha"),
})

time.Sleep(5 * time.Second)
log.Printf("Calling create")
driver.Create("fakeDriver", "a", "b")

time.Sleep(5 * time.Second)
log.Printf("Calling delete")
driver.Delete("fakeDriver", "a", "b")
}
}()
}
184 changes: 184 additions & 0 deletions pkg/grpc/infraclient/infraclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
Copyright (c) 2017 SAP SE or an SAP affiliate company. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package infraclient

import (
"context"
"io"

pb "github.com/gardener/machine-controller-manager/pkg/grpc/infrapb"
"github.com/golang/glog"
"google.golang.org/grpc"
)

// ExternalDriver structure mediates the communication with the machine-controller-manager
type ExternalDriver struct {
serverAddr string
options []grpc.DialOption
provider ExternalDriverProvider
connection *grpc.ClientConn
stream pb.Infragrpc_RegisterClient
}

// NewExternalDriver creates a new Driver instance.
func NewExternalDriver(serverAddr string, options []grpc.DialOption, provider ExternalDriverProvider) *ExternalDriver {
return &ExternalDriver{
serverAddr: serverAddr,
options: options,
provider: provider,
}
}

// Start starts the external driver.
func (d *ExternalDriver) Start() error {
conn, err := grpc.Dial(d.serverAddr, d.options...)
if err != nil {
glog.Fatalf("fail to dial: %v", err)
return err
}
d.connection = conn
client := pb.NewInfragrpcClient(conn)

go func() {
d.serveMCM(client)
}()

return nil
}

// Stop stops the external driver.
func (d *ExternalDriver) Stop() error {
stream := d.stream
//connection := d.connection

d.stream = nil
d.connection = nil

if stream != nil && stream.Context().Err() == nil {
stream.Send(&pb.DriverSide{
OperationType: "unregister",
})
stream.CloseSend()
}
var err error
/*
if connection != nil {
err = connection.Close()
}
*/

return err
}

func (d *ExternalDriver) serveMCM(client pb.InfragrpcClient) error {
glog.Infof("Registering with MCM...")
ctx := context.Background()

stream, err := client.Register(ctx)
if err != nil {
glog.Fatalf("%v.Register(_) = _, %v: ", client, err)
return err
}

d.stream = stream

for {
in, err := stream.Recv()
if err == io.EOF {
// read done.
return err
}
if err != nil {
glog.Fatalf("Failed to receive: %v", err)
return err
}

glog.Infof("Operation %s", in.OperationType)
opParams := in.GetOperationparams()
glog.Infof("create parameters: %v", opParams)

resp := pb.DriverSide{}
resp.OperationID = in.OperationID
resp.OperationType = in.OperationType

switch in.OperationType {
case "register":
machineClassType := d.provider.Register()
pMachineClassType := &machineClassType
gvk := pMachineClassType.GroupVersionKind()
resp.Response = &pb.DriverSide_RegisterResp{
RegisterResp: &pb.DriverSideRegisterationResp{
Name: "externalDriver",
Kind: gvk.Kind,
Group: gvk.Group,
Version: gvk.Version,
},
}
case "create":
var machineClass *MachineClassMeta
if opParams.MachineClassMetaData != nil {
machineClass = &MachineClassMeta{
Name: opParams.MachineClassMetaData.Name,
Revision: opParams.MachineClassMetaData.Revision,
}
}
providerID, nodename, err := d.provider.Create(machineClass, opParams.Credentials, opParams.MachineID, opParams.MachineName)

var sErr string
if err != nil {
sErr = err.Error()
}
resp.Response = &pb.DriverSide_Createresponse{
Createresponse: &pb.DriverSideCreateResp{
ProviderID: providerID,
Nodename: nodename,
Error: sErr,
},
}
case "delete":
err := d.provider.Delete(opParams.Credentials, opParams.MachineID)
var sErr string
if err != nil {
sErr = err.Error()
}
resp.Response = &pb.DriverSide_Deleteresponse{
Deleteresponse: &pb.DriverSideDeleteResp{
Error: sErr,
},
}
case "list":
vms, err := d.provider.List(opParams.MachineID)
list := []string{}

var sErr string
if err == nil {
for _, machineID := range vms {
list = append(list, machineID)
}
} else {
sErr = err.Error()
}
resp.Response = &pb.DriverSide_Listresponse{
Listresponse: &pb.DriverSideListResp{
List: list,
Error: sErr,
},
}
}

stream.Send(&resp)
}
}
34 changes: 34 additions & 0 deletions pkg/grpc/infraclient/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Copyright (c) 2017 SAP SE or an SAP affiliate company. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package infraclient

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// MachineClassMeta has metadata about the machine class.
type MachineClassMeta struct {
Name string
Revision int32
}

// ExternalDriverProvider interface must be implemented by the providers.
type ExternalDriverProvider interface {
Register() metav1.TypeMeta
Create(machineclass *MachineClassMeta, credentials, machineID, machineName string) (string, string, error)
Delete(credentials, machineID string) error
List(machineID string) (map[string]string, error)
}
Loading

0 comments on commit 07f83a0

Please sign in to comment.