Skip to content

Commit

Permalink
feat: add SchemaService.Validate to validate arbitrary entity (#443)
Browse files Browse the repository at this point in the history
* add SchemaService.Validate to validate arbitrary entity

* define EntityType
  • Loading branch information
randmonkey authored May 10, 2024
1 parent 353b66d commit 6c44e1f
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@
- [0.2.0](#020)
- [0.1.0](#010)

## Unreleased

- Add `Validate` method in `SchemaService` to validate arbitrary type of Kong
entities.
[#443](https://github.com/Kong/go-kong/pull/443)

## [v0.54.0]

> Release date: 2024/04/03
Expand Down
46 changes: 46 additions & 0 deletions kong/schema_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,36 @@ package kong

import (
"context"
"errors"
"fmt"
"net/http"
)

// EntityType describes a type of Kong entity.
type EntityType string

// Defition of constants for standard types of Kong entities.
const (
EntityTypeServices EntityType = "services"
EntityTypeRoutes EntityType = "routes"
EntityTypeUpstreams EntityType = "upstreams"
EntityTypeTargets EntityType = "targets"
EntityTypePlugins EntityType = "plugins"
EntityTypeConsumers EntityType = "consumers"
EntityTypeConsumerGroups EntityType = "consumer_groups"
EntityTypeSNIs EntityType = "snis"
EntityTypeCertificates EntityType = "certificates"
EntityTypeCACertificates EntityType = "ca_certificates"
EntityTypeTags EntityType = "tags"
)

// AbstractSchemaService handles schemas in Kong.
type AbstractSchemaService interface {
// Get fetches an entity schema from Kong.
Get(ctx context.Context, entity string) (Schema, error)
// Validate validates an arbitrary entity in Kong.
// Used for custom entities, or entities that do not have a Validate method in the corresponding service.
Validate(ctx context.Context, entityType EntityType, entity interface{}) (bool, string, error)
}

// SchemaService handles schemas in Kong.
Expand All @@ -17,6 +40,8 @@ type SchemaService service
// Schema represents an entity schema in Kong.
type Schema map[string]interface{}

var _ AbstractSchemaService = &SchemaService{}

// Get retrieves the full schema of kong entities.
func (s *SchemaService) Get(ctx context.Context, entity string) (Schema, error) {
req, err := s.client.NewRequest("GET", fmt.Sprintf("/schemas/%s", entity), nil, nil)
Expand All @@ -30,3 +55,24 @@ func (s *SchemaService) Get(ctx context.Context, entity string) (Schema, error)
}
return schema, nil
}

// Validate validates an arbitrary entity in Kong.
func (s *SchemaService) Validate(ctx context.Context, entityType EntityType, entity interface{}) (bool, string, error) {
endpoint := fmt.Sprintf("/schemas/%s/validate", entityType)
req, err := s.client.NewRequest("POST", endpoint, nil, entity)
if err != nil {
return false, "", err
}
resp, err := s.client.Do(ctx, req, nil)
if err != nil {
if resp == nil {
return false, "", err
}
var apiErr *APIError
if ok := errors.As(err, &apiErr); !ok || apiErr.Code() != http.StatusBadRequest {
return false, "", err
}
return false, apiErr.message, nil
}
return true, "", nil
}
48 changes: 48 additions & 0 deletions kong/schema_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,51 @@ func TestSchemaService(T *testing.T) {
assert.NoError(err)
}
}

func TestSchemaServiceValidate(t *testing.T) {
client, err := NewTestClient(nil, nil)
assert.NoError(t, err)
assert.NotNil(t, client)

testCases := []struct {
name string
entityType EntityType
entity any
valid bool
}{
{
name: "valid service should pass the validation",
entityType: EntityTypeServices,
entity: &Service{
Name: String("test.service"),
Host: String("foo.com"),
},
valid: true,
},
{
name: "invalid service (invalid protocol) should fail the validation",
entityType: EntityTypeServices,
entity: &Service{
Name: String("test.service"),
Host: String("foo.com"),
Protocol: String("not-exist-protocol"),
},
valid: false,
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
valid, msg, err := client.Schemas.Validate(defaultCtx, tc.entityType, tc.entity)
assert.NoError(t, err)
if tc.valid {
assert.True(t, valid)
assert.Empty(t, msg)
} else {
assert.False(t, valid)
assert.NotEmpty(t, msg)
}
})
}
}

0 comments on commit 6c44e1f

Please sign in to comment.