Ejemplo n.º 1
0
func setupSchemaLoaders() error {
	if schema != nil {
		return nil
	}

	var schemaRaw interface{}
	err := json.Unmarshal([]byte(schemaString), &schemaRaw)
	if err != nil {
		return err
	}

	schema = schemaRaw.(map[string]interface{})

	gojsonschema.FormatCheckers.Add("environment", environmentFormatChecker{})
	gojsonschema.FormatCheckers.Add("ports", portsFormatChecker{})
	gojsonschema.FormatCheckers.Add("expose", portsFormatChecker{})
	schemaLoader = gojsonschema.NewGoLoader(schemaRaw)

	definitions := schema["definitions"].(map[string]interface{})
	constraints := definitions["constraints"].(map[string]interface{})
	service := constraints["service"].(map[string]interface{})
	constraintSchemaLoader = gojsonschema.NewGoLoader(service)

	return nil
}
Ejemplo n.º 2
0
func (t *Test) evaluateBody() {
	if !t.Response.BodyCheck {
		return
	}
	if t.Response.BodyString != "" {
		b := []byte(t.Response.BodyString)
		if bytes.Equal(t.Response.body, b) {
			return
		}
		t.fail(fmt.Errorf("expect response body to equal %q, given %q", t.Response.BodyString, t.Response.body))
	} else if t.Response.BodyJsonSchema != nil {
		var v interface{}
		if err := json.Unmarshal(t.Response.body, &v); err != nil {
			t.fail(fmt.Errorf("response json body error %s", err))
			return
		}
		result, err := gojsonschema.Validate(gojsonschema.NewGoLoader(t.Response.BodyJsonSchema), gojsonschema.NewGoLoader(v))
		if err != nil {
			t.fail(fmt.Errorf("validation error %s", err))
			return
		}
		if !result.Valid() {
			for _, desc := range result.Errors() {
				t.fail(fmt.Errorf("JSON schema expect %s", desc))
			}
		}
	}
}
Ejemplo n.º 3
0
func TestGenJsonSchema(t *testing.T) {
	str := `
		{
		"k1":"a",
		"k2":1,
		"k3":[],
		"k4":["a"],
		"k5":[1],
		"k6":[1.1],
		"k7":{},
		"k8":{"a":1},
		"k9":{"a":1,"b":[]},
		"k10":{"a":1,"b":[],"c":{"d":1.1}},
		"k11":{"a":1,"b":[],"c":{"d":1.1,"f":["a"]}},
		"k12":{"a":1,"b":[{"a":1,"b":[1]}]}
		}
	`
	var obj interface{}
	err := json.Unmarshal([]byte(str), &obj)
	assert.Equal(t, err, nil)

	schema, err := GenJsonSchema(obj)
	assert.Equal(t, err, nil)

	_, err = json.MarshalIndent(schema, "", "  ")
	assert.Equal(t, err, nil)
	//	fmt.Println(string(bs))

	goSchema, err := gojsonschema.NewSchema(gojsonschema.NewGoLoader(schema))
	assert.Equal(t, err, nil)
	documentLoader := gojsonschema.NewStringLoader(str)
	ret, err := goSchema.Validate(documentLoader)
	assert.Equal(t, err, nil)
	assert.Equal(t, ret.Valid(), true)
}
Ejemplo n.º 4
0
//Validate validates json object using jsoncschema
func (schema *Schema) Validate(jsonSchema interface{}, object interface{}) error {
	schemaLoader := gojsonschema.NewGoLoader(jsonSchema)
	documentLoader := gojsonschema.NewGoLoader(object)
	result, err := gojsonschema.Validate(schemaLoader, documentLoader)
	if err != nil {
		return err
	}
	if result.Valid() {
		return nil
	}
	errDescription := "Json validation error:"
	for _, err := range result.Errors() {
		errDescription += fmt.Sprintf("\n\t%v,", err)
	}
	return fmt.Errorf(errDescription)
}
Ejemplo n.º 5
0
func (self *Route) validate(params interface{}, version int) (string, error) {
	route := self.Versions[version]
	if route == nil {
		return "", fmt.Errorf("Route version %v missing from %v route", version, self.Name)
	}
	if route.Schema == nil {
		return "", nil
	}
	documentLoader := gojsonschema.NewGoLoader(params)
	result, err := route.Schema.Validate(documentLoader)
	if err != nil {
		return "", err
	}
	if !result.Valid() {
		errors := make(map[string]string)
		for _, resultErr := range result.Errors() {
			errors[resultErr.Field()] = resultErr.Description()
		}
		errorsJson, err := json.Marshal(errors)
		if err != nil {
			return "", err
		}
		return string(errorsJson), nil
	}
	return "", nil
}
Ejemplo n.º 6
0
func validateServiceConstraintsv2(service RawService, serviceName string) error {
	if err := setupSchemaLoaders(servicesSchemaDataV2, &schemaV2, &schemaLoaderV2, &constraintSchemaLoaderV2); err != nil {
		return err
	}

	service = convertServiceKeysToStrings(service)

	var validationErrors []string

	dataLoader := gojsonschema.NewGoLoader(service)

	result, err := gojsonschema.Validate(constraintSchemaLoaderV2, dataLoader)
	if err != nil {
		return err
	}

	if !result.Valid() {
		for _, err := range result.Errors() {
			if err.Type() == "required" {
				_, containsImage := service["image"]
				_, containsBuild := service["build"]

				if containsBuild || !containsImage && !containsBuild {
					validationErrors = append(validationErrors, fmt.Sprintf("Service '%s' has neither an image nor a build context specified. At least one must be provided.", serviceName))
				}
			}
		}
		return fmt.Errorf(strings.Join(validationErrors, "\n"))
	}

	return nil
}
Ejemplo n.º 7
0
func FixDataWithSchema(data interface{}, schema interface{}) (dataFix interface{}, err error) {
	_, err = gojsonschema.NewSchema(gojsonschema.NewGoLoader(schema))
	if err != nil {
		return nil, err
	}

	return fixDataWithSchemaInterface(data, schema)
}
Ejemplo n.º 8
0
// ProcessObject checks if the object is valid from this schema's standpoint
// and returns an object with defaults set up according to schema's spec
func (j *JSONSchema) ProcessObject(in interface{}) (interface{}, error) {
	result, err := j.schema.Validate(gojsonschema.NewGoLoader(in))
	if err != nil {
		return nil, trace.Wrap(err)
	}
	if !result.Valid() {
		return nil, trace.Wrap(trace.Errorf("errors: %v", schemaErrors(result.Errors())))
	}
	return setDefaults(j.rawSchema, in), nil
}
Ejemplo n.º 9
0
func checkSchema(chain *chain, value, schema interface{}) {
	if chain.failed() {
		return
	}

	valueLoader := gojsonschema.NewGoLoader(value)

	var schemaLoader gojsonschema.JSONLoader

	if str, ok := toString(schema); ok {
		if ok, _ := regexp.MatchString(`^\w+://`, str); ok {
			schemaLoader = gojsonschema.NewReferenceLoader(str)
		} else {
			schemaLoader = gojsonschema.NewStringLoader(str)
		}
	} else {
		schemaLoader = gojsonschema.NewGoLoader(schema)
	}

	result, err := gojsonschema.Validate(schemaLoader, valueLoader)
	if err != nil {
		chain.fail("\n%s\n\nschema:\n%s\n\nvalue:\n%s",
			err.Error(),
			dumpSchema(schema),
			dumpValue(value))
		return
	}

	if !result.Valid() {
		errors := ""
		for _, err := range result.Errors() {
			errors += fmt.Sprintf(" %s\n", err)
		}

		chain.fail(
			"\njson schema validation failed, schema:\n%s\n\nvalue:%s\n\nerrors:\n%s",
			dumpSchema(schema),
			dumpValue(value),
			errors)

		return
	}
}
Ejemplo n.º 10
0
// ValidateJSON validates the given runtime against its defined schema
func (cfg *RuntimeOptions) ValidateJSON() error {
	schema := gojson.NewStringLoader(RuntimeSchema)
	doc := gojson.NewGoLoader(cfg)

	if result, err := gojson.Validate(schema, doc); err != nil {
		return err
	} else if !result.Valid() {
		return combineErrors(result.Errors())
	}

	return nil
}
Ejemplo n.º 11
0
func (s *JSONSchema) getSchema() (schema *gojsonschema.Schema, err error) {
	if s.schema != nil && !s.enumLoader.IsDirty() {
		return s.schema, nil
	}

	loader := gojsonschema.NewGoLoader(s.GetPreprocessed())
	s.schema, err = gojsonschema.NewSchema(loader)
	if err != nil {
		return
	}

	return s.schema, nil
}
Ejemplo n.º 12
0
func (c *InterfaceController) Update(w http.ResponseWriter, r *http.Request) {
	// Get ID
	id := mux.Vars(r)["id"]

	// Validate ObjectId
	if !bson.IsObjectIdHex(id) {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Get object id
	oid := bson.ObjectIdHex(id)

	// Initialize empty struct
	s := models.Interface{}

	// Decode JSON into struct
	err := json.NewDecoder(r.Body).Decode(&s)
	if err != nil {
		jsonError(w, r, "Failed to deconde JSON: "+err.Error(), http.StatusInternalServerError, c.envelope)
		return
	}

	// Validate input using JSON Schema
	docLoader := gojsonschema.NewGoLoader(s)
	schemaLoader := gojsonschema.NewReferenceLoader(c.schemaURI)

	res, err := gojsonschema.Validate(schemaLoader, docLoader)
	if err != nil {
		jsonError(w, r, "Failed to load schema: "+err.Error(), http.StatusInternalServerError, c.envelope)
		return
	}

	if !res.Valid() {
		var errors []string
		for _, e := range res.Errors() {
			errors = append(errors, fmt.Sprintf("%s: %s", e.Context().String(), e.Description()))
		}
		jsonError(w, r, errors, http.StatusInternalServerError, c.envelope)
		return
	}

	// Update entry
	if err := c.session.DB(c.database).C("interfaces").UpdateId(oid, s); err != nil {
		jsonError(w, r, err.Error(), http.StatusInternalServerError, c.envelope)
		return
	}

	// Write content-type, header and payload
	jsonWriter(w, r, s, http.StatusOK, c.envelope)
}
Ejemplo n.º 13
0
func (s schema) Validate(data interface{}) error {
	result, _ := s.schema.Validate(gojsonschema.NewGoLoader(data))
	if result.Valid() {
		return nil
	}
	msgs := []string{}
	for _, e := range result.Errors() {
		msgs = append(msgs, e.Description())
	}

	return singleIssue("", "Faild to validate sub-schema at {path}, errors: %s",
		strings.Join(msgs, ", "),
	)
}
Ejemplo n.º 14
0
// New returns JSON schema created from JSON byte string
// returns a valid schema or error if schema is invalid
func New(data []byte) (*JSONSchema, error) {
	j := JSONSchema{}
	err := json.Unmarshal(data, &j.rawSchema)
	if err != nil {
		return nil, trace.Wrap(err)
	}

	loader := gojsonschema.NewGoLoader(j.rawSchema)
	j.schema, err = gojsonschema.NewSchema(loader)
	if err != nil {
		return nil, trace.Wrap(err)
	}
	return &j, nil
}
Ejemplo n.º 15
0
// validateRequestData takes in a schema path and the request
// and will do the legwork of determining if the post data is valid
func validateRequestData(schemaPath string, r *web.Request) (
	document map[string]interface{},
	result *gojsonschema.Result,
	err error,
) {
	err = json.NewDecoder(r.Body).Decode(&document)
	if err == nil && schemaPath != "" {
		schemaLoader := gojsonschema.NewReferenceLoader(schemaPath)
		documentLoader := gojsonschema.NewGoLoader(document)

		result, err = gojsonschema.Validate(schemaLoader, documentLoader)
	}

	return document, result, err
}
Ejemplo n.º 16
0
func validateJSON(schema string, obj Entity) error {
	schemaObj := gojson.NewStringLoader(schema)
	doc := gojson.NewGoLoader(obj)

	if result, err := gojson.Validate(schemaObj, doc); err != nil {
		return err
	} else if !result.Valid() {
		var errors []string
		for _, err := range result.Errors() {
			errors = append(errors, fmt.Sprintf("%s\n", err))
		}
		return errored.New(strings.Join(errors, "\n"))
	}

	return nil
}
Ejemplo n.º 17
0
func validateV2(serviceMap RawServiceMap) error {
	if err := setupSchemaLoaders(servicesSchemaDataV2, &schemaV2, &schemaLoaderV2, &constraintSchemaLoaderV2); err != nil {
		return err
	}

	serviceMap = convertServiceMapKeysToStrings(serviceMap)

	dataLoader := gojsonschema.NewGoLoader(serviceMap)

	result, err := gojsonschema.Validate(schemaLoaderV2, dataLoader)
	if err != nil {
		return err
	}

	return generateErrorMessages(serviceMap, schemaV2, result)
}
Ejemplo n.º 18
0
// ProcessObject checks if the object is valid from this schema's standpoint
// and returns an object with defaults set up according to schema's spec
func (j *JSONSchema) ProcessObject(in interface{}) (interface{}, error) {
	defaults := setDefaults(j.rawSchema, in)

	result, err := j.schema.Validate(gojsonschema.NewGoLoader(defaults))
	if err != nil {
		return nil, trace.Wrap(err)
	}
	if !result.Valid() {
		errors := result.Errors()
		output := make([]string, len(errors))
		for i, err := range errors {
			output[i] = fmt.Sprintf("%v", err)
		}

		return nil, trace.Errorf("failed to validate: %v", strings.Join(output, ","))
	}
	return defaults, nil
}
Ejemplo n.º 19
0
func validateFunc(e Etcdtool, dir string, d interface{}) {
	// Map directory to routes.
	var schema string
	for _, r := range e.Routes {
		match, err := regexp.MatchString(r.Regexp, dir)
		if err != nil {
			fatal(err.Error())
		}
		if match {
			schema = r.Schema
		}
	}

	if schema == "" {
		fatal("Couldn't determine which JSON schema to use for validation")
	}

	/*
	   if schema == "" && len(c.Args()) == 1 {
	       fatal("You need to specify JSON schema URI")
	   }

	   if len(c.Args()) > 1 {
	       schema = c.Args()[1]
	   }
	*/

	// Validate directory.
	infof("Using JSON schema: %s", schema)
	schemaLoader := gojsonschema.NewReferenceLoader(schema)
	docLoader := gojsonschema.NewGoLoader(d)
	result, err := gojsonschema.Validate(schemaLoader, docLoader)
	if err != nil {
		fatal(err.Error())
	}

	// Print results.
	if !result.Valid() {
		for _, err := range result.Errors() {
			fmt.Printf("%s: %s\n", strings.Replace(err.Context().String("/"), "(root)", dir, 1), err.Description())
		}
		fatal("Data validation failed aborting")
	}
}
Ejemplo n.º 20
0
func (c *TenantController) Create(w http.ResponseWriter, r *http.Request) {
	// Initialize empty struct
	s := models.Tenant{}

	// Decode JSON into struct
	err := json.NewDecoder(r.Body).Decode(&s)
	if err != nil {
		jsonError(w, r, "Failed to deconde JSON: "+err.Error(), http.StatusInternalServerError, c.envelope)
		return
	}

	// Set ID
	s.ID = bson.NewObjectId()

	// Validate input using JSON Schema
	log.Printf("Using schema: %s", c.schemaURI)
	docLoader := gojsonschema.NewGoLoader(s)
	schemaLoader := gojsonschema.NewReferenceLoader(c.schemaURI)

	res, err := gojsonschema.Validate(schemaLoader, docLoader)
	if err != nil {
		jsonError(w, r, err.Error(), http.StatusInternalServerError, c.envelope)
		return
	}

	if !res.Valid() {
		var errors []string
		for _, e := range res.Errors() {
			errors = append(errors, fmt.Sprintf("%s: %s", e.Context().String(), e.Description()))
		}
		jsonError(w, r, errors, http.StatusInternalServerError, c.envelope)
		return
	}

	// Insert entry
	if err := c.session.DB(c.database).C("tenants").Insert(s); err != nil {
		jsonError(w, r, err.Error(), http.StatusInternalServerError, c.envelope)
		return
	}

	// Write content-type, header and payload
	jsonWriter(w, r, s, http.StatusCreated, c.envelope)
}
Ejemplo n.º 21
0
// Validate uses the jsonschema to validate the configuration
func Validate(config map[string]interface{}) error {
	schemaData, err := Asset("data/config_schema_v3.0.json")
	if err != nil {
		return err
	}

	schemaLoader := gojsonschema.NewStringLoader(string(schemaData))
	dataLoader := gojsonschema.NewGoLoader(config)

	result, err := gojsonschema.Validate(schemaLoader, dataLoader)
	if err != nil {
		return err
	}

	if !result.Valid() {
		return toError(result)
	}

	return nil
}
Ejemplo n.º 22
0
/**
 * Function validates JSON schema for `device` od `channel` models
 * By convention, Schema files must be kept as:
 * - ./models/deviceSchema.json
 * - ./models/channelSchema.json
 */
func validateJsonSchema(model string, body map[string]interface{}) bool {
	pwd, _ := os.Getwd()
	schemaLoader := gojsonschema.NewReferenceLoader("file://" + pwd +
		"/schema/" + model + "Schema.json")
	bodyLoader := gojsonschema.NewGoLoader(body)
	result, err := gojsonschema.Validate(schemaLoader, bodyLoader)
	if err != nil {
		log.Print(err.Error())
	}

	if result.Valid() {
		fmt.Printf("The document is valid\n")
		return true
	} else {
		fmt.Printf("The document is not valid. See errors :\n")
		for _, desc := range result.Errors() {
			fmt.Printf("- %s\n", desc)
		}
		return false
	}
}
Ejemplo n.º 23
0
// NewSchema creates a Schema that wraps a jsonschema.
// The jsonschema can be specified as a JSON string or a hierarchy of
//   * map[string]interface{}
//   * []interface{}
//   * string
//   * float64
//   * bool
//   * nil
func NewSchema(jsonschema interface{}) (Schema, error) {
	var loader gojsonschema.JSONLoader
	if s, ok := jsonschema.(string); ok {
		var target interface{}
		if err := json.Unmarshal([]byte(s), &target); err != nil {
			return nil, fmt.Errorf("Failed to parse JSON string, error: %s", err)
		}
		jsonschema = target
	}
	obj, ok := jsonschema.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("Expected map[string]interface{} got: %T", jsonschema)
	}
	loader = gojsonschema.NewGoLoader(jsonschema)

	s, err := gojsonschema.NewSchema(loader)
	if err != nil {
		return nil, err
	}

	return schema{schema: s, raw: obj}, nil
}
Ejemplo n.º 24
0
func (self *Route) validate(params map[string]interface{}) (string, error) {
	if self.Schema == nil {
		return "", nil
	}
	documentLoader := gojsonschema.NewGoLoader(params)
	result, err := self.Schema.Validate(documentLoader)
	if err != nil {
		return "", err
	}
	if !result.Valid() {
		errors := make(map[string]string)
		for _, resultErr := range result.Errors() {
			errors[resultErr.Field()] = resultErr.Description()
		}
		errorsJson, err := json.Marshal(errors)
		if err != nil {
			return "", err
		}
		return string(errorsJson), nil
	}
	return "", nil
}
Ejemplo n.º 25
0
func validateServiceConstraints(service RawService, serviceName string) error {
	if err := setupSchemaLoaders(); err != nil {
		return err
	}

	service = convertServiceKeysToStrings(service)

	var validationErrors []string

	dataLoader := gojsonschema.NewGoLoader(service)

	result, err := gojsonschema.Validate(constraintSchemaLoader, dataLoader)
	if err != nil {
		return err
	}

	if !result.Valid() {
		for _, err := range result.Errors() {
			if err.Type() == "number_any_of" {
				_, containsImage := service["image"]
				_, containsBuild := service["build"]
				_, containsDockerfile := service["dockerfile"]

				if containsImage && containsBuild {
					validationErrors = append(validationErrors, fmt.Sprintf("Service '%s' has both an image and build path specified. A service can either be built to image or use an existing image, not both.", serviceName))
				} else if !containsImage && !containsBuild {
					validationErrors = append(validationErrors, fmt.Sprintf("Service '%s' has neither an image nor a build path specified. Exactly one must be provided.", serviceName))
				} else if containsImage && containsDockerfile {
					validationErrors = append(validationErrors, fmt.Sprintf("Service '%s' has both an image and alternate Dockerfile. A service can either be built to image or use an existing image, not both.", serviceName))
				}
			}
		}

		return fmt.Errorf(strings.Join(validationErrors, "\n"))
	}

	return nil
}
Ejemplo n.º 26
0
// Validation rules:
//   Grammar expr is:
//     String that starts with $ -> Look for type match
//     String (without $) -> Exact match
//     Object -> Treat object as a JSON schema and validate input with it
//     Otherwise -> No match
func matchExpr(input *simplejson.Json, grammar *simplejson.Json, diag bool) bool {
	if grammar == nil && input == nil {
		return true
	}
	if grammar == nil || input == nil {
		if diag {
			log.Printf("Grammar was %v while input was %v", grammar, nil)
		}
		return false
	}
	stype, err := grammar.String()
	if err == nil {
		switch stype {
		case "$_":
			return true
		case "$string":
			_, terr := input.String()
			if terr != nil && diag {
				log.Printf("Input wasn't a string")
			}
			return terr == nil
		case "$bool":
			_, terr := input.Bool()
			if terr != nil && diag {
				log.Printf("Input wasn't a bool")
			}
			return terr == nil
		case "$int":
			_, terr := input.Int64()
			if terr != nil && diag {
				log.Printf("Input wasn't an int")
			}
			return terr == nil
		case "$number":
			_, terr := input.Float64()
			if terr != nil && diag {
				log.Printf("Input wasn't a number")
			}
			return terr == nil
		default:
			is, terr := input.String()
			log.Printf("treated as literal")
			return terr == nil && is == stype
		}
	}
	mtype, err := grammar.Map()
	if err == nil {
		schemaLoader := gojsonschema.NewGoLoader(mtype)
		documentLoader := gojsonschema.NewGoLoader(input)

		result, err := gojsonschema.Validate(schemaLoader, documentLoader)
		if err != nil {
			log.Printf("Validation error: %v", err)

			return false
		}

		for _, e := range result.Errors() {
			log.Printf("  JSON Schema validation failed because: %s", e)
		}
		return result.Valid()
	}
	return false
}
Ejemplo n.º 27
0
func (v *UserValidater) Validate(u *User) (error, []string) {
	dl := gojsonschema.NewGoLoader(u)
	return validate(v.sl, dl)
}
Ejemplo n.º 28
0
func validate(serviceMap RawServiceMap) error {
	if err := setupSchemaLoaders(); err != nil {
		return err
	}

	serviceMap = convertServiceMapKeysToStrings(serviceMap)

	var validationErrors []string

	dataLoader := gojsonschema.NewGoLoader(serviceMap)

	result, err := gojsonschema.Validate(schemaLoader, dataLoader)
	if err != nil {
		return err
	}

	// gojsonschema can create extraneous "additional_property_not_allowed" errors in some cases
	// If this is set, and the error is at root level, skip over that error
	skipRootAdditionalPropertyError := false

	if !result.Valid() {
		for i := 0; i < len(result.Errors()); i++ {
			err := result.Errors()[i]

			if skipRootAdditionalPropertyError && err.Type() == "additional_property_not_allowed" && err.Context().String() == "(root)" {
				skipRootAdditionalPropertyError = false
				continue
			}

			if err.Context().String() == "(root)" {
				switch err.Type() {
				case "additional_property_not_allowed":
					validationErrors = append(validationErrors, fmt.Sprintf("Invalid service name '%s' - only [a-zA-Z0-9\\._\\-] characters are allowed", err.Field()))
				default:
					validationErrors = append(validationErrors, err.Description())
				}
			} else {
				skipRootAdditionalPropertyError = true

				serviceName := serviceNameFromErrorField(err.Field())
				key := keyNameFromErrorField(err.Field())

				switch err.Type() {
				case "additional_property_not_allowed":
					validationErrors = append(validationErrors, unsupportedConfigMessage(key, result.Errors()[i+1]))
				case "number_one_of":
					validationErrors = append(validationErrors, fmt.Sprintf("Service '%s' configuration key '%s' %s", serviceName, key, oneOfMessage(serviceMap, schema, err, result.Errors()[i+1])))

					// Next error handled in oneOfMessage, skip over it
					i++
				case "invalid_type":
					validationErrors = append(validationErrors, invalidTypeMessage(serviceName, key, err))
				case "required":
					validationErrors = append(validationErrors, fmt.Sprintf("Service '%s' option '%s' is invalid, %s", serviceName, key, err.Description()))
				case "missing_dependency":
					dependency := err.Details()["dependency"].(string)
					validationErrors = append(validationErrors, fmt.Sprintf("Invalid configuration for '%s' service: dependency '%s' is not satisfied", serviceName, dependency))
				case "unique":
					contextWithDuplicates := getValue(serviceMap, err.Context().String())
					validationErrors = append(validationErrors, fmt.Sprintf("Service '%s' configuration key '%s' value %s has non-unique elements", serviceName, key, contextWithDuplicates))
				default:
					validationErrors = append(validationErrors, fmt.Sprintf("Service '%s' configuration key %s value %s", serviceName, key, err.Description()))
				}
			}
		}

		return fmt.Errorf(strings.Join(validationErrors, "\n"))
	}

	return nil
}
Ejemplo n.º 29
0
func Validate(stackName string, filePath string) error {
	stack := Stack{Name: ""}
	data, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	yaml.Unmarshal(data, &stack.Definition)

	nameLoader := gojsonschema.NewStringLoader(NAME_SCHEMA)
	schemaLoader := gojsonschema.NewStringLoader(SERVICE_SCHEMA)

	documentLoader := gojsonschema.NewGoLoader(stackName)
	result, err := gojsonschema.Validate(nameLoader, documentLoader)
	if err != nil {
		return err
	}

	if !result.Valid() {
		message := "Stack name not valid: "
		for _, desc := range result.Errors() {
			message += fmt.Sprintf("'%s' %s\n", desc.Value, desc.Description)
		}
		return errors.New(message)
	}

	stack.SetDefaults()

	for name, definition := range stack.Definition {
		documentLoader := gojsonschema.NewGoLoader(name)
		result, err := gojsonschema.Validate(nameLoader, documentLoader)
		if err != nil {
			return err
		}

		if !result.Valid() {
			var message string
			message = "Service name not valid: "
			for _, desc := range result.Errors() {
				message += fmt.Sprintf("'%s' %s\n", desc.Value, desc.Description)
			}
			return errors.New(message)
		}

		documentLoader = gojsonschema.NewGoLoader(definition)
		result, err = gojsonschema.Validate(schemaLoader, documentLoader)
		if err != nil {
			return err
		}

		if !result.Valid() {
			var message string
			message = "Service " + name + " not valid. see errors:\n"
			for _, desc := range result.Errors() {
				message += fmt.Sprintf("%s: '%s' %s\n", desc.Context.String()[7:], desc.Value, desc.Description)
			}
			return errors.New(message)
		}

		for _, link := range definition.Links {
			linkAndAlias := strings.Split(link, ":")
			var linkedService string
			if len(linkAndAlias) == 2 {
				linkedService = linkAndAlias[1]
			} else {
				linkedService = linkAndAlias[0]
			}
			_, ok := stack.Definition[linkedService]
			if !ok {
				return fmt.Errorf("Linked service '%s' in service '%s' does not exist\n", linkedService, name)
			}
		}

		for _, volumesFrom := range definition.Volumes_from {
			_, ok := stack.Definition[volumesFrom]
			if !ok {
				return fmt.Errorf("VolumesFrom '%s' in service '%s' does not exist\n", volumesFrom, name)
			}
		}
	}
	return nil
}
Ejemplo n.º 30
0
// validateCommandFunc validate data using JSON Schema.
func validateCommandFunc(c *cli.Context) {
	if len(c.Args()) == 0 {
		fatal("You need to specify directory")
	}
	dir := c.Args()[0]

	// Remove trailing slash.
	if dir != "/" {
		dir = strings.TrimRight(dir, "/")
	}
	infof("Using dir: %s", dir)

	// Load configuration file.
	e := loadConfig(c)

	// New dir API.
	ki := newKeyAPI(e)

	// Map directory to routes.
	var schema string
	for _, r := range e.Routes {
		match, err := regexp.MatchString(r.Regexp, dir)
		if err != nil {
			fatal(err.Error())
		}
		if match {
			schema = r.Schema
		}
	}

	if schema == "" && len(c.Args()) == 1 {
		fatal("You need to specify JSON schema URI")
	}

	if len(c.Args()) > 1 {
		schema = c.Args()[1]
	}

	// Get directory.
	ctx, cancel := contextWithCommandTimeout(c)
	resp, err := ki.Get(ctx, dir, &client.GetOptions{Recursive: true})
	cancel()
	if err != nil {
		fatal(err.Error())
	}
	m := etcdmap.Map(resp.Node)

	// Validate directory.
	infof("Using JSON schema: %s", schema)
	schemaLoader := gojsonschema.NewReferenceLoader(schema)
	docLoader := gojsonschema.NewGoLoader(m)
	result, err := gojsonschema.Validate(schemaLoader, docLoader)
	if err != nil {
		fatal(err.Error())
	}

	// Print results.
	if !result.Valid() {
		for _, err := range result.Errors() {
			fmt.Printf("%s: %s\n", strings.Replace(err.Context().String("/"), "(root)", dir, 1), err.Description())
		}
	}
}