...

Source file src/github.com/google/gnostic-models/compiler/extensions.go

Documentation: github.com/google/gnostic-models/compiler

     1  // Copyright 2017 Google LLC. 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  	"strings"
    22  
    23  	"google.golang.org/protobuf/proto"
    24  	"google.golang.org/protobuf/types/known/anypb"
    25  	yaml "gopkg.in/yaml.v3"
    26  
    27  	extensions "github.com/google/gnostic-models/extensions"
    28  )
    29  
    30  // ExtensionHandler describes a binary that is called by the compiler to handle specification extensions.
    31  type ExtensionHandler struct {
    32  	Name string
    33  }
    34  
    35  // CallExtension calls a binary extension handler.
    36  func CallExtension(context *Context, in *yaml.Node, extensionName string) (handled bool, response *anypb.Any, err error) {
    37  	if context == nil || context.ExtensionHandlers == nil {
    38  		return false, nil, nil
    39  	}
    40  	handled = false
    41  	for _, handler := range *(context.ExtensionHandlers) {
    42  		response, err = handler.handle(in, extensionName)
    43  		if response == nil {
    44  			continue
    45  		} else {
    46  			handled = true
    47  			break
    48  		}
    49  	}
    50  	return handled, response, err
    51  }
    52  
    53  func (extensionHandlers *ExtensionHandler) handle(in *yaml.Node, extensionName string) (*anypb.Any, error) {
    54  	if extensionHandlers.Name != "" {
    55  		yamlData, _ := yaml.Marshal(in)
    56  		request := &extensions.ExtensionHandlerRequest{
    57  			CompilerVersion: &extensions.Version{
    58  				Major: 0,
    59  				Minor: 1,
    60  				Patch: 0,
    61  			},
    62  			Wrapper: &extensions.Wrapper{
    63  				Version:       "unknown", // TODO: set this to the type/version of spec being parsed.
    64  				Yaml:          string(yamlData),
    65  				ExtensionName: extensionName,
    66  			},
    67  		}
    68  		requestBytes, _ := proto.Marshal(request)
    69  		cmd := exec.Command(extensionHandlers.Name)
    70  		cmd.Stdin = bytes.NewReader(requestBytes)
    71  		output, err := cmd.Output()
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		response := &extensions.ExtensionHandlerResponse{}
    76  		err = proto.Unmarshal(output, response)
    77  		if err != nil || !response.Handled {
    78  			return nil, err
    79  		}
    80  		if len(response.Errors) != 0 {
    81  			return nil, fmt.Errorf("Errors when parsing: %+v for field %s by vendor extension handler %s. Details %+v", in, extensionName, extensionHandlers.Name, strings.Join(response.Errors, ","))
    82  		}
    83  		return response.Value, nil
    84  	}
    85  	return nil, nil
    86  }
    87  

View as plain text