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