github.com/ystia/yorc/v4@v4.3.0/plugin/config.go (about)

     1  // Copyright 2018 Bull S.A.S. Atos Technologies - Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois, France.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package plugin
    16  
    17  import (
    18  	"github.com/ystia/yorc/v4/storage"
    19  	"net/rpc"
    20  	"text/template"
    21  
    22  	plugin "github.com/hashicorp/go-plugin"
    23  	"github.com/pkg/errors"
    24  
    25  	"github.com/ystia/yorc/v4/config"
    26  	"github.com/ystia/yorc/v4/helper/consulutil"
    27  )
    28  
    29  // ConfigManager allows to send configuration to the plugin
    30  //
    31  // This is public for use by reflexion and should be considered as private to this package.
    32  // Please do not use it directly.
    33  type ConfigManager interface {
    34  	SetupConfig(cfg config.Configuration) error
    35  }
    36  
    37  type defaultConfigManager struct {
    38  }
    39  
    40  func (cm *defaultConfigManager) SetupConfig(cfg config.Configuration) error {
    41  
    42  	// Configuring standard log to use Hashicorp hclog within the plugin so that
    43  	// these standard logs can be parsed and filtered in the Yorc server according
    44  	// to their log level
    45  	initPluginStdLog()
    46  
    47  	// Currently we only use this plugin part to initialize the Consul publisher
    48  	cClient, err := cfg.GetNewConsulClient()
    49  	if err != nil {
    50  		return err
    51  	}
    52  	kv := cClient.KV()
    53  	maxPubSub := cfg.Consul.PubMaxRoutines
    54  	if maxPubSub == 0 {
    55  		maxPubSub = config.DefaultConsulPubMaxRoutines
    56  	}
    57  	consulutil.InitConsulPublisher(maxPubSub, kv)
    58  
    59  	// Load stores in order to allow plugins to access different stores
    60  	return storage.LoadStores(cfg)
    61  }
    62  
    63  // ConfigManagerPlugin is public for use by reflexion and should be considered as private to this package.
    64  // Please do not use it directly.
    65  type ConfigManagerPlugin struct {
    66  	PluginConfigManager ConfigManager
    67  }
    68  
    69  // ConfigManagerServer is public for use by reflexion and should be considered as private to this package.
    70  // Please do not use it directly.
    71  type ConfigManagerServer struct {
    72  	PluginConfigManager ConfigManager
    73  	Broker              *plugin.MuxBroker
    74  }
    75  
    76  // Server is public for use by reflexion and should be considered as private to this package.
    77  // Please do not use it directly.
    78  func (p *ConfigManagerPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
    79  	return &ConfigManagerServer{PluginConfigManager: p.PluginConfigManager, Broker: b}, nil
    80  }
    81  
    82  // ConfigManagerClient is public for use by reflexion and should be considered as private to this package.
    83  // Please do not use it directly.
    84  type ConfigManagerClient struct {
    85  	Client *rpc.Client
    86  	Broker *plugin.MuxBroker
    87  }
    88  
    89  // Client is public for use by reflexion and should be considered as private to this package.
    90  // Please do not use it directly.
    91  func (p *ConfigManagerPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
    92  	return &ConfigManagerClient{Client: c, Broker: b}, nil
    93  }
    94  
    95  // ConfigManagerSetupConfigArgs is public for use by reflexion and should be considered as private to this package.
    96  // Please do not use it directly.
    97  type ConfigManagerSetupConfigArgs struct {
    98  	Cfg config.Configuration
    99  	ID  uint32
   100  }
   101  
   102  // ConfigManagerSetupConfigResponse is public for use by reflexion and should be considered as private to this package.
   103  // Please do not use it directly.
   104  type ConfigManagerSetupConfigResponse struct {
   105  	Error *RPCError
   106  }
   107  
   108  // SetupConfig is public for use by reflexion and should be considered as private to this package.
   109  // Please do not use it directly.
   110  func (s *ConfigManagerServer) SetupConfig(args *ConfigManagerSetupConfigArgs, reply *ConfigManagerSetupConfigResponse) error {
   111  	var resp ConfigManagerSetupConfigResponse
   112  	conn, err := s.Broker.Dial(args.ID)
   113  	if err != nil {
   114  		resp.Error = NewRPCError(err)
   115  		*reply = resp
   116  		return nil
   117  	}
   118  
   119  	client := rpc.NewClient(conn)
   120  	// TODO check how and when to close the client connection: when plugin stops ? using a custom operation ?
   121  	// client.Close()
   122  	ctrc := &ConfigTemplateResolverClient{Client: client}
   123  	config.DefaultConfigTemplateResolver = ctrc
   124  
   125  	err = s.PluginConfigManager.SetupConfig(args.Cfg)
   126  
   127  	if err != nil {
   128  		resp.Error = NewRPCError(err)
   129  	}
   130  	*reply = resp
   131  	return nil
   132  }
   133  
   134  // SetupConfig is public for use by reflexion and should be considered as private to this package.
   135  // Please do not use it directly.
   136  func (c *ConfigManagerClient) SetupConfig(cfg config.Configuration) error {
   137  	var resp ConfigManagerSetupConfigResponse
   138  	id := c.Broker.NextId()
   139  
   140  	// TODO: Check how and when to stop this routine when plugin stops ? using a custom operation ?
   141  	go c.Broker.AcceptAndServe(id, &ConfigTemplateResolverServer{})
   142  	args := ConfigManagerSetupConfigArgs{Cfg: cfg, ID: id}
   143  
   144  	err := c.Client.Call("Plugin.SetupConfig", &args, &resp)
   145  	if err != nil {
   146  		return errors.Wrap(err, "Failed call ConfigManager setup for plugin")
   147  	}
   148  	return toError(resp.Error)
   149  }
   150  
   151  // ConfigTemplateResolverClient is public for use by reflexion and should be considered as private to this package.
   152  // Please do not use it directly.
   153  type ConfigTemplateResolverClient struct {
   154  	Client *rpc.Client
   155  }
   156  
   157  // SetTemplatesFunctions is public for use by reflexion and should be considered as private to this package.
   158  // Please do not use it directly.
   159  func (c *ConfigTemplateResolverClient) SetTemplatesFunctions(fm template.FuncMap) {
   160  	// Not Implemented
   161  }
   162  
   163  // Disable allows to disable configuration templates usage
   164  func (c *ConfigTemplateResolverClient) Disable() {
   165  	// Not implemented
   166  }
   167  
   168  // Enable allows to enable configuration templates usage
   169  func (c *ConfigTemplateResolverClient) Enable() {
   170  	// Not implemented
   171  }
   172  
   173  // ConfigTemplateResolverResolveValueWithTemplatesArgs is public for use by reflexion and should be considered as private to this package.
   174  // Please do not use it directly.
   175  type ConfigTemplateResolverResolveValueWithTemplatesArgs struct {
   176  	Key   string
   177  	Value interface{}
   178  }
   179  
   180  // ConfigTemplateResolverResolveValueWithTemplatesResponse is public for use by reflexion and should be considered as private to this package.
   181  // Please do not use it directly.
   182  type ConfigTemplateResolverResolveValueWithTemplatesResponse struct {
   183  	Value interface{}
   184  }
   185  
   186  // ResolveValueWithTemplates is public for use by reflexion and should be considered as private to this package.
   187  // Please do not use it directly.
   188  func (c *ConfigTemplateResolverClient) ResolveValueWithTemplates(key string, value interface{}) interface{} {
   189  	var resp ConfigTemplateResolverResolveValueWithTemplatesResponse
   190  	args := ConfigTemplateResolverResolveValueWithTemplatesArgs{Key: key, Value: value}
   191  
   192  	err := c.Client.Call("Plugin.ResolveValueWithTemplates", &args, &resp)
   193  	if err != nil {
   194  		return nil
   195  	}
   196  	return resp.Value
   197  
   198  }
   199  
   200  // ConfigTemplateResolverServer is public for use by reflexion and should be considered as private to this package.
   201  // Please do not use it directly.
   202  type ConfigTemplateResolverServer struct{}
   203  
   204  // ResolveValueWithTemplates is public for use by reflexion and should be considered as private to this package.
   205  // Please do not use it directly.
   206  func (s *ConfigTemplateResolverServer) ResolveValueWithTemplates(args *ConfigTemplateResolverResolveValueWithTemplatesArgs, reply *ConfigTemplateResolverResolveValueWithTemplatesResponse) error {
   207  
   208  	res := config.DefaultConfigTemplateResolver.ResolveValueWithTemplates(args.Key, args.Value)
   209  
   210  	*reply = ConfigTemplateResolverResolveValueWithTemplatesResponse{res}
   211  	return nil
   212  }