github.com/ystia/yorc/v4@v4.3.0/plugin/delegate.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 "context" 19 "net/rpc" 20 21 plugin "github.com/hashicorp/go-plugin" 22 "github.com/pkg/errors" 23 24 "github.com/ystia/yorc/v4/config" 25 "github.com/ystia/yorc/v4/events" 26 "github.com/ystia/yorc/v4/prov" 27 ) 28 29 // DelegateExecutor is an extension of prov.DelegateExecutor that expose its supported node types 30 type DelegateExecutor interface { 31 prov.DelegateExecutor 32 // Returns a list of regexp matches for node types 33 GetSupportedTypes() ([]string, error) 34 } 35 36 // DelegatePlugin is public for use by reflexion and should be considered as private to this package. 37 // Please do not use it directly. 38 type DelegatePlugin struct { 39 F func() prov.DelegateExecutor 40 SupportedTypes []string 41 } 42 43 // Server is public for use by reflexion and should be considered as private to this package. 44 // Please do not use it directly. 45 func (p *DelegatePlugin) Server(b *plugin.MuxBroker) (interface{}, error) { 46 des := &DelegateExecutorServer{Broker: b, SupportedTypes: p.SupportedTypes} 47 if p.F != nil { 48 des.Delegate = p.F() 49 } else if len(p.SupportedTypes) > 0 { 50 return nil, NewRPCErrorFromMessage("If DelegateSupportedTypes is defined then you have to defined a DelegateFunc") 51 } 52 return des, nil 53 } 54 55 // Client is public for use by reflexion and should be considered as private to this package. 56 // Please do not use it directly. 57 func (p *DelegatePlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { 58 return &DelegateExecutorClient{Broker: b, Client: c}, nil 59 } 60 61 // DelegateExecutorClient is public for use by reflexion and should be considered as private to this package. 62 // Please do not use it directly. 63 type DelegateExecutorClient struct { 64 Broker *plugin.MuxBroker 65 Client *rpc.Client 66 } 67 68 // ExecDelegate is public for use by reflexion and should be considered as private to this package. 69 // Please do not use it directly. 70 func (c *DelegateExecutorClient) ExecDelegate(ctx context.Context, conf config.Configuration, taskID, deploymentID, nodeName, delegateOperation string) error { 71 lof, ok := events.FromContext(ctx) 72 if !ok { 73 return errors.New("Missing contextual log optionnal fields") 74 } 75 76 id := c.Broker.NextId() 77 closeChan := make(chan struct{}, 0) 78 defer close(closeChan) 79 go clientMonitorContextCancellation(ctx, closeChan, id, c.Broker) 80 81 var resp DelegateExecutorExecDelegateResponse 82 args := &DelegateExecutorExecDelegateArgs{ 83 ChannelID: id, 84 Conf: conf, 85 TaskID: taskID, 86 DeploymentID: deploymentID, 87 NodeName: nodeName, 88 DelegateOperation: delegateOperation, 89 LogOptionalFields: lof, 90 } 91 err := c.Client.Call("Plugin.ExecDelegate", args, &resp) 92 if err != nil { 93 return err 94 } 95 return toError(resp.Error) 96 } 97 98 // DelegateExecutorServer is public for use by reflexion and should be considered as private to this package. 99 // Please do not use it directly. 100 type DelegateExecutorServer struct { 101 Broker *plugin.MuxBroker 102 Delegate prov.DelegateExecutor 103 SupportedTypes []string 104 } 105 106 // DelegateExecutorExecDelegateArgs is public for use by reflexion and should be considered as private to this package. 107 // Please do not use it directly. 108 type DelegateExecutorExecDelegateArgs struct { 109 ChannelID uint32 110 Conf config.Configuration 111 TaskID string 112 DeploymentID string 113 NodeName string 114 DelegateOperation string 115 LogOptionalFields events.LogOptionalFields 116 } 117 118 // DelegateExecutorExecDelegateResponse is public for use by reflexion and should be considered as private to this package. 119 // Please do not use it directly. 120 type DelegateExecutorExecDelegateResponse struct { 121 Error *RPCError 122 } 123 124 // ExecDelegate is public for use by reflexion and should be considered as private to this package. 125 // Please do not use it directly. 126 func (s *DelegateExecutorServer) ExecDelegate(args *DelegateExecutorExecDelegateArgs, reply *DelegateExecutorExecDelegateResponse) error { 127 ctx, cancelFunc := context.WithCancel(events.NewContext(context.Background(), args.LogOptionalFields)) 128 defer cancelFunc() 129 130 go s.Broker.AcceptAndServe(args.ChannelID, &RPCContextCanceller{CancelFunc: cancelFunc}) 131 err := s.Delegate.ExecDelegate(ctx, args.Conf, args.TaskID, args.DeploymentID, args.NodeName, args.DelegateOperation) 132 133 var resp DelegateExecutorExecDelegateResponse 134 if err != nil { 135 resp.Error = NewRPCError(err) 136 } 137 *reply = resp 138 return nil 139 } 140 141 // GetSupportedTypes is public for use by reflexion and should be considered as private to this package. 142 // Please do not use it directly. 143 func (s *DelegateExecutorServer) GetSupportedTypes(_ interface{}, reply *DelegateExecutorGetTypesResponse) error { 144 *reply = DelegateExecutorGetTypesResponse{SupportedTypes: s.SupportedTypes} 145 return nil 146 } 147 148 // DelegateExecutorGetTypesResponse is public for use by reflexion and should be considered as private to this package. 149 // Please do not use it directly. 150 type DelegateExecutorGetTypesResponse struct { 151 SupportedTypes []string 152 Error *RPCError 153 } 154 155 // GetSupportedTypes is public for use by reflexion and should be considered as private to this package. 156 // Please do not use it directly. 157 func (c *DelegateExecutorClient) GetSupportedTypes() ([]string, error) { 158 var resp DelegateExecutorGetTypesResponse 159 err := c.Client.Call("Plugin.GetSupportedTypes", new(interface{}), &resp) 160 if err != nil { 161 return nil, errors.Wrap(err, "Failed to get supported types for delegate plugin") 162 } 163 164 return resp.SupportedTypes, toError(resp.Error) 165 }