github.com/ferranbt/nomad@v0.9.3-0.20190607002617-85c449b7667c/plugins/base/plugin_test.go (about)

     1  package base
     2  
     3  import (
     4  	"testing"
     5  
     6  	pb "github.com/golang/protobuf/proto"
     7  	plugin "github.com/hashicorp/go-plugin"
     8  	"github.com/hashicorp/nomad/nomad/structs"
     9  	"github.com/hashicorp/nomad/plugins/shared/hclspec"
    10  	"github.com/stretchr/testify/require"
    11  	"github.com/zclconf/go-cty/cty"
    12  	"github.com/zclconf/go-cty/cty/msgpack"
    13  )
    14  
    15  func TestBasePlugin_PluginInfo_GRPC(t *testing.T) {
    16  	t.Parallel()
    17  	require := require.New(t)
    18  
    19  	var (
    20  		apiVersions = []string{"v0.1.0", "v0.1.1"}
    21  	)
    22  
    23  	const (
    24  		pluginVersion = "v0.2.1"
    25  		pluginName    = "mock"
    26  	)
    27  
    28  	knownType := func() (*PluginInfoResponse, error) {
    29  		info := &PluginInfoResponse{
    30  			Type:              PluginTypeDriver,
    31  			PluginApiVersions: apiVersions,
    32  			PluginVersion:     pluginVersion,
    33  			Name:              pluginName,
    34  		}
    35  		return info, nil
    36  	}
    37  	unknownType := func() (*PluginInfoResponse, error) {
    38  		info := &PluginInfoResponse{
    39  			Type:              "bad",
    40  			PluginApiVersions: apiVersions,
    41  			PluginVersion:     pluginVersion,
    42  			Name:              pluginName,
    43  		}
    44  		return info, nil
    45  	}
    46  
    47  	mock := &MockPlugin{
    48  		PluginInfoF: knownType,
    49  	}
    50  
    51  	client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
    52  		PluginTypeBase: &PluginBase{Impl: mock},
    53  	})
    54  	defer server.Stop()
    55  	defer client.Close()
    56  
    57  	raw, err := client.Dispense(PluginTypeBase)
    58  	if err != nil {
    59  		t.Fatalf("err: %s", err)
    60  	}
    61  
    62  	impl, ok := raw.(BasePlugin)
    63  	if !ok {
    64  		t.Fatalf("bad: %#v", raw)
    65  	}
    66  
    67  	resp, err := impl.PluginInfo()
    68  	require.NoError(err)
    69  	require.Equal(apiVersions, resp.PluginApiVersions)
    70  	require.Equal(pluginVersion, resp.PluginVersion)
    71  	require.Equal(pluginName, resp.Name)
    72  	require.Equal(PluginTypeDriver, resp.Type)
    73  
    74  	// Swap the implementation to return an unknown type
    75  	mock.PluginInfoF = unknownType
    76  	_, err = impl.PluginInfo()
    77  	require.Error(err)
    78  	require.Contains(err.Error(), "unknown type")
    79  }
    80  
    81  func TestBasePlugin_ConfigSchema(t *testing.T) {
    82  	t.Parallel()
    83  	require := require.New(t)
    84  
    85  	mock := &MockPlugin{
    86  		ConfigSchemaF: func() (*hclspec.Spec, error) {
    87  			return TestSpec, nil
    88  		},
    89  	}
    90  
    91  	client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
    92  		PluginTypeBase: &PluginBase{Impl: mock},
    93  	})
    94  	defer server.Stop()
    95  	defer client.Close()
    96  
    97  	raw, err := client.Dispense(PluginTypeBase)
    98  	if err != nil {
    99  		t.Fatalf("err: %s", err)
   100  	}
   101  
   102  	impl, ok := raw.(BasePlugin)
   103  	if !ok {
   104  		t.Fatalf("bad: %#v", raw)
   105  	}
   106  
   107  	specOut, err := impl.ConfigSchema()
   108  	require.NoError(err)
   109  	require.True(pb.Equal(TestSpec, specOut))
   110  }
   111  
   112  func TestBasePlugin_SetConfig(t *testing.T) {
   113  	t.Parallel()
   114  	require := require.New(t)
   115  
   116  	var receivedData []byte
   117  	mock := &MockPlugin{
   118  		PluginInfoF: func() (*PluginInfoResponse, error) {
   119  			return &PluginInfoResponse{Type: PluginTypeDriver}, nil
   120  		},
   121  		ConfigSchemaF: func() (*hclspec.Spec, error) {
   122  			return TestSpec, nil
   123  		},
   124  		SetConfigF: func(cfg *Config) error {
   125  			receivedData = cfg.PluginConfig
   126  			return nil
   127  		},
   128  	}
   129  
   130  	client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
   131  		PluginTypeBase: &PluginBase{Impl: mock},
   132  	})
   133  	defer server.Stop()
   134  	defer client.Close()
   135  
   136  	raw, err := client.Dispense(PluginTypeBase)
   137  	if err != nil {
   138  		t.Fatalf("err: %s", err)
   139  	}
   140  
   141  	impl, ok := raw.(BasePlugin)
   142  	if !ok {
   143  		t.Fatalf("bad: %#v", raw)
   144  	}
   145  
   146  	config := cty.ObjectVal(map[string]cty.Value{
   147  		"foo": cty.StringVal("v1"),
   148  		"bar": cty.NumberIntVal(1337),
   149  		"baz": cty.BoolVal(true),
   150  	})
   151  	cdata, err := msgpack.Marshal(config, config.Type())
   152  	require.NoError(err)
   153  	require.NoError(impl.SetConfig(&Config{PluginConfig: cdata}))
   154  	require.Equal(cdata, receivedData)
   155  
   156  	// Decode the value back
   157  	var actual TestConfig
   158  	require.NoError(structs.Decode(receivedData, &actual))
   159  	require.Equal("v1", actual.Foo)
   160  	require.EqualValues(1337, actual.Bar)
   161  	require.True(actual.Baz)
   162  }