github.com/bdwilliams/libcompose@v0.3.1-0.20160826154243-d81a9bdacff0/config/schema_helpers.go (about)

     1  package config
     2  
     3  import (
     4  	"encoding/json"
     5  	"strings"
     6  
     7  	"github.com/docker/go-connections/nat"
     8  	"github.com/xeipuuv/gojsonschema"
     9  )
    10  
    11  var (
    12  	schemaLoader           gojsonschema.JSONLoader
    13  	constraintSchemaLoader gojsonschema.JSONLoader
    14  	schema                 map[string]interface{}
    15  )
    16  
    17  type (
    18  	environmentFormatChecker struct{}
    19  	portsFormatChecker       struct{}
    20  )
    21  
    22  func (checker environmentFormatChecker) IsFormat(input string) bool {
    23  	// If the value is a boolean, a warning should be given
    24  	// However, we can't determine type since gojsonschema converts the value to a string
    25  	// Adding a function with an interface{} parameter to gojsonschema is probably the best way to handle this
    26  	return true
    27  }
    28  
    29  func (checker portsFormatChecker) IsFormat(input string) bool {
    30  	_, _, err := nat.ParsePortSpecs([]string{input})
    31  	return err == nil
    32  }
    33  
    34  func setupSchemaLoaders() error {
    35  	if schema != nil {
    36  		return nil
    37  	}
    38  
    39  	var schemaRaw interface{}
    40  	err := json.Unmarshal([]byte(schemaV1), &schemaRaw)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	schema = schemaRaw.(map[string]interface{})
    46  
    47  	gojsonschema.FormatCheckers.Add("environment", environmentFormatChecker{})
    48  	gojsonschema.FormatCheckers.Add("ports", portsFormatChecker{})
    49  	gojsonschema.FormatCheckers.Add("expose", portsFormatChecker{})
    50  	schemaLoader = gojsonschema.NewGoLoader(schemaRaw)
    51  
    52  	definitions := schema["definitions"].(map[string]interface{})
    53  	constraints := definitions["constraints"].(map[string]interface{})
    54  	service := constraints["service"].(map[string]interface{})
    55  	constraintSchemaLoader = gojsonschema.NewGoLoader(service)
    56  
    57  	return nil
    58  }
    59  
    60  // gojsonschema doesn't provide a list of valid types for a property
    61  // This parses the schema manually to find all valid types
    62  func parseValidTypesFromSchema(schema map[string]interface{}, context string) []string {
    63  	contextSplit := strings.Split(context, ".")
    64  	key := contextSplit[len(contextSplit)-1]
    65  
    66  	definitions := schema["definitions"].(map[string]interface{})
    67  	service := definitions["service"].(map[string]interface{})
    68  	properties := service["properties"].(map[string]interface{})
    69  	property := properties[key].(map[string]interface{})
    70  
    71  	var validTypes []string
    72  
    73  	if val, ok := property["oneOf"]; ok {
    74  		validConditions := val.([]interface{})
    75  
    76  		for _, validCondition := range validConditions {
    77  			condition := validCondition.(map[string]interface{})
    78  			validTypes = append(validTypes, condition["type"].(string))
    79  		}
    80  	} else if val, ok := property["$ref"]; ok {
    81  		reference := val.(string)
    82  		if reference == "#/definitions/string_or_list" {
    83  			return []string{"string", "array"}
    84  		} else if reference == "#/definitions/list_of_strings" {
    85  			return []string{"array"}
    86  		} else if reference == "#/definitions/list_or_dict" {
    87  			return []string{"array", "object"}
    88  		}
    89  	}
    90  
    91  	return validTypes
    92  }