blob: cd8b8cce6fec0963c84361c10d3b37288e86fda2 [file] [log] [blame]
// 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 injector
import (
"fmt"
"net"
"reflect"
"regexp"
"runtime"
"strings"
)
// AnnotationValidateFunc is the type of validate function
type AnnotationValidateFunc func(annotation, value string) error
var (
//AnnotationValidateFuncs define all validate functions
AnnotationValidateFuncs = []AnnotationValidateFunc{
ValidateServiceName,
ValidateBackendServices,
ValidateIPv4OrHostname,
}
)
// FindValidateFunc is find the validate function for an annotation
func FindValidateFunc(funcName string) AnnotationValidateFunc {
for _, f := range AnnotationValidateFuncs {
// extract the function name into a string , it will be like following
// github.com/apache/skywalking-swck/pkg/operator/injector.ValidateBool
fname := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
// get real validate function name in injector
index := strings.LastIndex(fname, ".")
funcname := fname[index+1:]
if funcname == funcName {
return f
}
}
return nil
}
//ValidateServiceName validates the ServiceName is nil or not
func ValidateServiceName(annotation, value string) error {
if value == "" {
return fmt.Errorf("%s error:the service name is nil", annotation)
}
return nil
}
//ValidateBackendServices validates an annotation's value is valid backend services
func ValidateBackendServices(annotation, value string) error {
services := []string{value}
if strings.Contains(value, ",") {
services = strings.Split(value, ",")
}
allEmpty := true
for _, service := range services {
service = strings.TrimSpace(service)
if service == "" {
continue
}
allEmpty = false
err := ValidateIPv4OrHostname(annotation, service)
if err != nil {
return err
}
}
if allEmpty {
return fmt.Errorf("%s error:every service is nil", annotation)
}
return nil
}
//ValidateIPv4OrHostname validates an annotation's value is valid ipv4 or hostname
func ValidateIPv4OrHostname(annotation, service string) error {
service = strings.TrimSpace(service)
colonIndex := strings.LastIndex(service, ":")
host := service
if colonIndex != -1 {
host = service[:colonIndex]
}
if host == "" {
return fmt.Errorf("%s error:the service name is nil", annotation)
}
ip := net.ParseIP(host)
if ip != nil && ip.To4() != nil {
return nil
}
match, err := regexp.MatchString(`^([a-zA-Z0-9][a-zA-Z0-9_-]{0,62})(\.[a-zA-Z0-9_][a-zA-Z0-9_-]{0,62})*?$`,
host)
if err != nil {
return fmt.Errorf("%s error:%s", annotation, err.Error())
}
if !match {
return fmt.Errorf("%s=%s error:not a valid ipv4 or hostname", annotation, host)
}
return nil
}