Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / googleapis / gnostic / compiler / extension-handler.go
1 // Copyright 2017 Google Inc. All Rights Reserved.
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 compiler
16
17 import (
18         "bytes"
19         "fmt"
20         "os/exec"
21
22         "strings"
23
24         "errors"
25
26         "github.com/golang/protobuf/proto"
27         "github.com/golang/protobuf/ptypes/any"
28         ext_plugin "github.com/googleapis/gnostic/extensions"
29         yaml "gopkg.in/yaml.v2"
30 )
31
32 // ExtensionHandler describes a binary that is called by the compiler to handle specification extensions.
33 type ExtensionHandler struct {
34         Name string
35 }
36
37 // HandleExtension calls a binary extension handler.
38 func HandleExtension(context *Context, in interface{}, extensionName string) (bool, *any.Any, error) {
39         handled := false
40         var errFromPlugin error
41         var outFromPlugin *any.Any
42
43         if context != nil && context.ExtensionHandlers != nil && len(*(context.ExtensionHandlers)) != 0 {
44                 for _, customAnyProtoGenerator := range *(context.ExtensionHandlers) {
45                         outFromPlugin, errFromPlugin = customAnyProtoGenerator.handle(in, extensionName)
46                         if outFromPlugin == nil {
47                                 continue
48                         } else {
49                                 handled = true
50                                 break
51                         }
52                 }
53         }
54         return handled, outFromPlugin, errFromPlugin
55 }
56
57 func (extensionHandlers *ExtensionHandler) handle(in interface{}, extensionName string) (*any.Any, error) {
58         if extensionHandlers.Name != "" {
59                 binary, _ := yaml.Marshal(in)
60
61                 request := &ext_plugin.ExtensionHandlerRequest{}
62
63                 version := &ext_plugin.Version{}
64                 version.Major = 0
65                 version.Minor = 1
66                 version.Patch = 0
67                 request.CompilerVersion = version
68
69                 request.Wrapper = &ext_plugin.Wrapper{}
70
71                 request.Wrapper.Version = "v2"
72                 request.Wrapper.Yaml = string(binary)
73                 request.Wrapper.ExtensionName = extensionName
74
75                 requestBytes, _ := proto.Marshal(request)
76                 cmd := exec.Command(extensionHandlers.Name)
77                 cmd.Stdin = bytes.NewReader(requestBytes)
78                 output, err := cmd.Output()
79
80                 if err != nil {
81                         fmt.Printf("Error: %+v\n", err)
82                         return nil, err
83                 }
84                 response := &ext_plugin.ExtensionHandlerResponse{}
85                 err = proto.Unmarshal(output, response)
86                 if err != nil {
87                         fmt.Printf("Error: %+v\n", err)
88                         fmt.Printf("%s\n", string(output))
89                         return nil, err
90                 }
91                 if !response.Handled {
92                         return nil, nil
93                 }
94                 if len(response.Error) != 0 {
95                         message := fmt.Sprintf("Errors when parsing: %+v for field %s by vendor extension handler %s. Details %+v", in, extensionName, extensionHandlers.Name, strings.Join(response.Error, ","))
96                         return nil, errors.New(message)
97                 }
98                 return response.Value, nil
99         }
100         return nil, nil
101 }