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 }