github.com/ystia/yorc/v4@v4.3.0/plugin/action.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 // ActionOperator is an extension of prov.ActionOperator that expose its supported action types 30 type ActionOperator interface { 31 prov.ActionOperator 32 // Returns an array of action types types 33 GetActionTypes() ([]string, error) 34 } 35 36 // ActionPlugin is public for use by reflexion and should be considered as private to this package. 37 // Please do not use it directly. 38 type ActionPlugin struct { 39 F func() prov.ActionOperator 40 ActionTypes []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 *ActionPlugin) Server(b *plugin.MuxBroker) (interface{}, error) { 46 aes := &ActionOperatorServer{Broker: b, ActionTypes: p.ActionTypes} 47 if p.F != nil { 48 aes.ActionOperator = p.F() 49 } else if len(p.ActionTypes) > 0 { 50 return nil, errors.New("If ActionTypes is defined then you have to defined an ActionFunc") 51 } 52 53 return aes, nil 54 } 55 56 // Client is public for use by reflexion and should be considered as private to this package. 57 // Please do not use it directly. 58 func (p *ActionPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { 59 return &ActionOperatorClient{Broker: b, Client: c}, nil 60 } 61 62 // ActionOperatorClient is public for use by reflexion and should be considered as private to this package. 63 // Please do not use it directly. 64 type ActionOperatorClient struct { 65 Broker *plugin.MuxBroker 66 Client *rpc.Client 67 } 68 69 // ExecAction is public for use by reflexion and should be considered as private to this package. 70 // Please do not use it directly. 71 func (c *ActionOperatorClient) ExecAction(ctx context.Context, conf config.Configuration, taskID, deploymentID string, action *prov.Action) (bool, error) { 72 lof, ok := events.FromContext(ctx) 73 if !ok { 74 return false, errors.New("Missing contextual log optional fields") 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 ActionOperatorExecOperationResponse 82 args := &ActionOperatorExecOperationArgs{ 83 ChannelID: id, 84 Conf: conf, 85 TaskID: taskID, 86 DeploymentID: deploymentID, 87 Action: action, 88 LogOptionalFields: lof, 89 } 90 err := c.Client.Call("Plugin.ExecAction", args, &resp) 91 if err != nil { 92 return false, errors.Wrap(err, "Failed to call ExecOperation for plugin") 93 } 94 return resp.Deregister, toError(resp.Error) 95 } 96 97 // ActionOperatorServer is public for use by reflexion and should be considered as private to this package. 98 // Please do not use it directly. 99 type ActionOperatorServer struct { 100 Broker *plugin.MuxBroker 101 ActionOperator prov.ActionOperator 102 ActionTypes []string 103 } 104 105 // ActionOperatorExecOperationArgs is public for use by reflexion and should be considered as private to this package. 106 // Please do not use it directly. 107 type ActionOperatorExecOperationArgs struct { 108 ChannelID uint32 109 Conf config.Configuration 110 TaskID string 111 DeploymentID string 112 Action *prov.Action 113 LogOptionalFields events.LogOptionalFields 114 } 115 116 // ActionOperatorExecOperationResponse is public for use by reflexion and should be considered as private to this package. 117 // Please do not use it directly. 118 type ActionOperatorExecOperationResponse struct { 119 Deregister bool 120 Error *RPCError 121 } 122 123 // ExecAction is public for use by reflexion and should be considered as private to this package. 124 // Please do not use it directly. 125 func (s *ActionOperatorServer) ExecAction(args *ActionOperatorExecOperationArgs, reply *ActionOperatorExecOperationResponse) error { 126 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 var resp ActionOperatorExecOperationResponse 132 var err error 133 resp.Deregister, err = s.ActionOperator.ExecAction(ctx, args.Conf, args.TaskID, args.DeploymentID, args.Action) 134 if err != nil { 135 resp.Error = NewRPCError(err) 136 } 137 *reply = resp 138 return nil 139 } 140 141 // GetActionTypes 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 *ActionOperatorServer) GetActionTypes(_ interface{}, reply *ActionOperatorGetTypesResponse) error { 144 *reply = ActionOperatorGetTypesResponse{ActionTypes: s.ActionTypes} 145 return nil 146 } 147 148 // ActionOperatorGetTypesResponse is public for use by reflexion and should be considered as private to this package. 149 // Please do not use it directly. 150 type ActionOperatorGetTypesResponse struct { 151 ActionTypes []string 152 Error *RPCError 153 } 154 155 // GetActionTypes 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 *ActionOperatorClient) GetActionTypes() ([]string, error) { 158 var resp ActionOperatorGetTypesResponse 159 err := c.Client.Call("Plugin.GetActionTypes", new(interface{}), &resp) 160 if err != nil { 161 return nil, errors.Wrap(err, "Failed to get supported types for plugin") 162 } 163 return resp.ActionTypes, toError(resp.Error) 164 }