github.com/ystia/yorc/v4@v4.3.0/plugin/serve.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 "encoding/gob" 19 "text/template" 20 21 "github.com/hashicorp/go-plugin" 22 23 "github.com/ystia/yorc/v4/config" 24 "github.com/ystia/yorc/v4/events" 25 "github.com/ystia/yorc/v4/prov" 26 "github.com/ystia/yorc/v4/vault" 27 ) 28 29 const ( 30 // DelegatePluginName is the name of Delegates Plugins it could be used as a lookup key in Client.Dispense 31 DelegatePluginName = "delegate" 32 // DefinitionsPluginName is the name of Delegates Plugins it could be used as a lookup key in Client.Dispense 33 DefinitionsPluginName = "definitions" 34 // ConfigManagerPluginName is the name of ConfigManager plugin it could be used as a lookup key in Client.Dispense 35 ConfigManagerPluginName = "cfgManager" 36 // OperationPluginName is the name of Operation Plugins it could be used as a lookup key in Client.Dispense 37 OperationPluginName = "operation" 38 // ActionPluginName is the name of Action Plugins it could be used as a lookup key in Client.Dispense 39 ActionPluginName = "action" 40 // InfraUsageCollectorPluginName is the name of InfraUsageCollector Plugins it could be used as a lookup key in Client.Dispense 41 InfraUsageCollectorPluginName = "infraUsageCollector" 42 ) 43 44 // HandshakeConfig are used to just do a basic handshake between 45 // a plugin and host. If the handshake fails, a user friendly error is shown. 46 // This prevents users from executing bad plugins or executing a plugin 47 // directory. It is a UX feature, not a security feature. 48 var HandshakeConfig = plugin.HandshakeConfig{ 49 ProtocolVersion: 3, 50 MagicCookieKey: "YORC_PLUG_API", 51 MagicCookieValue: "a3292e718f7c96578aae47e92b7475394e72e6da3de3455554462ba15dde56d1b3187ad0e5f809f50767e0d10ca6944fdf4c6c412380d3aa083b9e8951f7101e", 52 } 53 54 // DelegateFunc is a function that is called when creating a plugin server 55 type DelegateFunc func() prov.DelegateExecutor 56 57 // OperationFunc is a function that is called when creating a plugin server 58 type OperationFunc func() prov.OperationExecutor 59 60 // ActionFunc is a function that is called when creating a plugin server 61 type ActionFunc func() prov.ActionOperator 62 63 // InfraUsageCollectorFunc is a function that is called when creating a plugin server 64 type InfraUsageCollectorFunc func() prov.InfraUsageCollector 65 66 // ServeOpts are the configurations to serve a plugin. 67 type ServeOpts struct { 68 DelegateFunc DelegateFunc 69 DelegateSupportedTypes []string 70 Definitions map[string][]byte 71 OperationFunc OperationFunc 72 OperationSupportedArtifactTypes []string 73 ActionFunc ActionFunc 74 ActionTypes []string 75 InfraUsageCollectorFunc InfraUsageCollectorFunc 76 InfraUsageCollectorSupportedInfras []string 77 } 78 79 // Serve serves a plugin. This function never returns and should be the final 80 // function called in the main function of the plugin. 81 func Serve(opts *ServeOpts) { 82 SetupPluginCommunication() 83 84 // Configuring Yorc logs to use Hashicorp hclog in the plugin so that 85 // these logs can be parsed and filtered in the Yorc server according to their 86 // log level 87 initPluginYorcLog() 88 89 // Cannot configure here standard log to use Hashicorp hclog, as next call 90 // plugin.Serve() is setting standard log output to os.Stderr. 91 // This will be done in config.go by the defaultConfigManager 92 93 plugin.Serve(&plugin.ServeConfig{ 94 HandshakeConfig: HandshakeConfig, 95 Plugins: getPlugins(opts), 96 Logger: hclogger, 97 }) 98 } 99 100 func getPlugins(opts *ServeOpts) map[string]plugin.Plugin { 101 if opts == nil { 102 opts = new(ServeOpts) 103 } 104 return map[string]plugin.Plugin{ 105 DelegatePluginName: &DelegatePlugin{F: opts.DelegateFunc, SupportedTypes: opts.DelegateSupportedTypes}, 106 OperationPluginName: &OperationPlugin{F: opts.OperationFunc, SupportedTypes: opts.OperationSupportedArtifactTypes}, 107 ActionPluginName: &ActionPlugin{F: opts.ActionFunc, ActionTypes: opts.ActionTypes}, 108 DefinitionsPluginName: &DefinitionsPlugin{Definitions: opts.Definitions}, 109 ConfigManagerPluginName: &ConfigManagerPlugin{&defaultConfigManager{}}, 110 InfraUsageCollectorPluginName: &InfraUsageCollectorPlugin{F: opts.InfraUsageCollectorFunc, SupportedInfras: opts.InfraUsageCollectorSupportedInfras}, 111 } 112 } 113 114 // SetupPluginCommunication makes mandatory actions to allow RPC calls btw server and plugins 115 // This must be called both by serve and each plugin 116 func SetupPluginCommunication() { 117 // As we have type []interface{} in the config.Configuration structure, we need to register it before sending config from yorc server to plugins 118 gob.Register(make(map[string]interface{}, 0)) 119 gob.Register(make(events.LogOptionalFields, 0)) 120 gob.Register(make([]interface{}, 0)) 121 gob.Register(make([]string, 0)) 122 gob.RegisterName("DynamicMap", &config.DynamicMap{}) 123 gob.Register(template.FuncMap{}) 124 gob.Register(new(vault.Client)) 125 gob.RegisterName("RPCError", RPCError{}) 126 }