api/validate/validate.go (234 lines of code) (raw):
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// Package validate provides functions to validate the provided objects.
package validate
import (
"errors"
commonv1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v1"
databasev1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v1"
)
// Group validates the provided Group object.
func Group(group *commonv1.Group) error {
if group.Metadata == nil {
return errors.New("metadata is required")
}
if group.Metadata.Name == "" {
return errors.New("metadata.name is required")
}
if group.Catalog == commonv1.Catalog_CATALOG_UNSPECIFIED {
return errors.New("catalog is unspecified")
}
if group.Catalog == commonv1.Catalog_CATALOG_PROPERTY {
if group.ResourceOpts == nil {
return errors.New("resourceOpts is nil")
}
if group.ResourceOpts.ShardNum <= 0 {
return errors.New("shardNum is invalid")
}
if group.ResourceOpts.SegmentInterval != nil {
return errors.New("segmentInterval should be nil")
}
if group.ResourceOpts.Ttl != nil {
return errors.New("ttl should be nil")
}
return nil
}
return GroupForStreamOrMeasure(group)
}
// GroupForStreamOrMeasure validates the provided Group object for Stream or Measure.
// It checks for nil values, empty strings, and unspecified enum values.
func GroupForStreamOrMeasure(group *commonv1.Group) error {
if group == nil {
return errors.New("group is nil")
}
if group.Metadata == nil {
return errors.New("group metadata is nil")
}
if group.Metadata.Name == "" {
return errors.New("group name is empty")
}
if group.Catalog == commonv1.Catalog_CATALOG_UNSPECIFIED {
return errors.New("group catalog is unspecified")
}
if group.ResourceOpts == nil {
return errors.New("group resourceOpts is nil")
}
if group.ResourceOpts.ShardNum <= 0 {
return errors.New("group shardNum is invalid")
}
if group.ResourceOpts.SegmentInterval == nil {
return errors.New("group segmentInterval is nil")
}
if group.ResourceOpts.SegmentInterval.Num <= 0 {
return errors.New("group segmentInterval num is invalid")
}
if group.ResourceOpts.SegmentInterval.Unit == commonv1.IntervalRule_UNIT_UNSPECIFIED {
return errors.New("group segmentInterval unit is unspecified")
}
if group.ResourceOpts.Ttl == nil {
return errors.New("group ttl is nil")
}
if group.ResourceOpts.Ttl.Num <= 0 {
return errors.New("group ttl num is invalid")
}
if group.ResourceOpts.Ttl.Unit == commonv1.IntervalRule_UNIT_UNSPECIFIED {
return errors.New("group ttl unit is unspecified")
}
return nil
}
// Stream validates the provided Stream object.
// It checks for nil values, empty strings, and unspecified enum values.
func Stream(stream *databasev1.Stream) error {
if stream == nil {
return errors.New("stream is nil")
}
if stream.Metadata == nil {
return errors.New("stream metadata is nil")
}
if stream.Metadata.Name == "" {
return errors.New("stream name is empty")
}
if stream.Metadata.Group == "" {
return errors.New("stream group is empty")
}
if len(stream.TagFamilies) == 0 {
return errors.New("stream tag families is empty")
}
if stream.Entity == nil {
return errors.New("stream entity is nil")
}
if len(stream.Entity.TagNames) == 0 {
return errors.New("stream entity tag names is empty")
}
return tagFamily(stream.TagFamilies)
}
// Measure validates the provided Measure object.
// It checks for nil values, empty strings, and unspecified enum values.
func Measure(measure *databasev1.Measure) error {
if measure == nil {
return errors.New("measure is nil")
}
if measure.Metadata == nil {
return errors.New("measure metadata is nil")
}
if measure.Metadata.Name == "" {
return errors.New("measure name is empty")
}
if measure.Metadata.Group == "" {
return errors.New("measure group is empty")
}
if measure.Entity == nil {
return errors.New("measure entity is nil")
}
if len(measure.Entity.TagNames) == 0 {
return errors.New("measure entity tag names is empty")
}
for i := range measure.Fields {
if measure.Fields[i].Name == "" {
return errors.New("field name is empty")
}
if measure.Fields[i].FieldType == databasev1.FieldType_FIELD_TYPE_UNSPECIFIED {
return errors.New("field type is unspecified")
}
if measure.Fields[i].CompressionMethod == databasev1.CompressionMethod_COMPRESSION_METHOD_UNSPECIFIED {
return errors.New("compression method is unspecified")
}
if measure.Fields[i].CompressionMethod == databasev1.CompressionMethod_COMPRESSION_METHOD_UNSPECIFIED {
return errors.New("compression method is unspecified")
}
}
if len(measure.TagFamilies) == 0 {
return errors.New("measure tag families is empty")
}
if measure.IndexMode && len(measure.Fields) > 0 {
return errors.New("index mode is enabled, but fields are not empty")
}
return tagFamily(measure.TagFamilies)
}
func tagFamily(tagFamilies []*databasev1.TagFamilySpec) error {
for i := range tagFamilies {
if tagFamilies[i].Name == "" {
return errors.New("tag family name is empty")
}
for j := range tagFamilies[i].Tags {
if tagFamilies[i].Tags[j].Name == "" {
return errors.New("tag name is empty")
}
if tagFamilies[i].Tags[j].Type == databasev1.TagType_TAG_TYPE_UNSPECIFIED {
return errors.New("tag type is unspecified")
}
}
}
return nil
}
// IndexRule validates the provided IndexRule object.
// It checks for nil values, empty strings, and unspecified enum values.
func IndexRule(indexRule *databasev1.IndexRule) error {
if indexRule == nil {
return errors.New("indexRule is nil")
}
if indexRule.Metadata == nil {
return errors.New("indexRule metadata is nil")
}
if indexRule.Metadata.Name == "" {
return errors.New("indexRule name is empty")
}
if indexRule.Metadata.Group == "" {
return errors.New("indexRule group is empty")
}
if indexRule.Metadata.Id <= 0 {
return errors.New("indexRule id is invalid")
}
if len(indexRule.Tags) == 0 {
return errors.New("indexRule tags is empty")
}
if indexRule.Type == databasev1.IndexRule_TYPE_UNSPECIFIED {
return errors.New("indexRule type is unspecified")
}
return nil
}
// IndexRuleBinding validates the provided IndexRuleBinding object.
// It checks for nil values, empty strings, and unspecified enum values.
func IndexRuleBinding(indexRuleBinding *databasev1.IndexRuleBinding) error {
if indexRuleBinding == nil {
return errors.New("indexRuleBinding is nil")
}
if indexRuleBinding.Metadata == nil {
return errors.New("indexRuleBinding metadata is nil")
}
if indexRuleBinding.Metadata.Name == "" {
return errors.New("indexRuleBinding name is empty")
}
if indexRuleBinding.Metadata.Group == "" {
return errors.New("indexRuleBinding group is empty")
}
if indexRuleBinding.Subject == nil {
return errors.New("indexRuleBinding subject is nil")
}
if indexRuleBinding.Subject.Name == "" {
return errors.New("indexRuleBinding subject name is empty")
}
if indexRuleBinding.Subject.Catalog == commonv1.Catalog_CATALOG_UNSPECIFIED {
return errors.New("indexRuleBinding subject catalog is unspecified")
}
if len(indexRuleBinding.Rules) == 0 {
return errors.New("indexRuleBinding rules is empty")
}
return nil
}
// TopNAggregation validates the provided TopNAggregation object.
// It checks for nil values, empty strings, and unspecified enum values.
func TopNAggregation(topNAggregation *databasev1.TopNAggregation) error {
if topNAggregation == nil {
return errors.New("topNAggregation is nil")
}
if topNAggregation.Metadata == nil {
return errors.New("topNAggregation metadata is nil")
}
if topNAggregation.Metadata.Name == "" {
return errors.New("topNAggregation name is empty")
}
if topNAggregation.Metadata.Group == "" {
return errors.New("topNAggregation group is empty")
}
if topNAggregation.SourceMeasure == nil {
return errors.New("topNAggregation sourceMeasure is nil")
}
if topNAggregation.SourceMeasure.Name == "" {
return errors.New("topNAggregation sourceMeasure name is empty")
}
if topNAggregation.SourceMeasure.Group == "" {
return errors.New("topNAggregation sourceMeasure group is empty")
}
if topNAggregation.CountersNumber <= 0 {
return errors.New("topNAggregation countersNumber is invalid")
}
if topNAggregation.FieldName == "" {
return errors.New("topNAggregation fieldName is empty")
}
return nil
}