diff --git a/api-runtime/common-runtime/CCMCommon.go b/api-runtime/common-runtime/CCMCommon.go index 313d480bd..e71b78839 100644 --- a/api-runtime/common-runtime/CCMCommon.go +++ b/api-runtime/common-runtime/CCMCommon.go @@ -78,6 +78,16 @@ func CreateImage(connectionName string, rsType string, reqInfo cres.ImageReqInfo return nil, err } + emptyPermissionList := []string{ + "resources.IID:SystemId", + } + + err = ValidateStruct(reqInfo, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } + cldConn, err := ccm.GetCloudConnection(connectionName) if err != nil { cblog.Error(err) @@ -614,6 +624,15 @@ func RegisterVPC(connectionName string, userIID cres.IID) (*cres.VPCInfo, error) return nil, err } + emptyPermissionList := []string{ + } + + err = ValidateStruct(userIID, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } + rsType := rsVPC cldConn, err := ccm.GetCloudConnection(connectionName) @@ -840,6 +859,19 @@ func CreateVPC(connectionName string, rsType string, reqInfo cres.VPCReqInfo) (* return nil, err } + emptyPermissionList := []string{ + "resources.IID:SystemId", + "resources.VPCReqInfo:IPv4_CIDR", // because can be unused in some VPC + "resources.KeyValue:Key", // because unusing key-value list + "resources.KeyValue:Value", // because unusing key-value list + } + + err = ValidateStruct(reqInfo, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } + cldConn, err := ccm.GetCloudConnection(connectionName) if err != nil { cblog.Error(err) @@ -1321,6 +1353,15 @@ func RegisterSecurity(connectionName string, vpcUserID string, userIID cres.IID) return nil, err } + emptyPermissionList := []string{ + } + + err = ValidateStruct(userIID, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } + rsType := rsSG cldConn, err := ccm.GetCloudConnection(connectionName) @@ -1428,6 +1469,19 @@ func CreateSecurity(connectionName string, rsType string, reqInfo cres.SecurityR return nil, err } + /* + emptyPermissionList := []string{ + "resources.IID:SystemId", + "resources.SecurityReqInfo:Direction", // because can be unused in some CSP + "resources.SecurityRuleInfo:CIDR", // because can be set without soruce CIDR + } + + err = ValidateStruct(reqInfo, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } +*/ //+++++++++++++++++++++++++++++++++++++++++++ // set VPC's SystemId vpcIIDInfo, err := iidRWLock.GetIID(iidm.IIDSGROUP, connectionName, rsVPC, reqInfo.VpcIID) @@ -1748,6 +1802,15 @@ func RegisterKey(connectionName string, userIID cres.IID) (*cres.KeyPairInfo, er return nil, err } + emptyPermissionList := []string{ + } + + err = ValidateStruct(userIID, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } + rsType := rsKey cldConn, err := ccm.GetCloudConnection(connectionName) @@ -1821,6 +1884,16 @@ func CreateKey(connectionName string, rsType string, reqInfo cres.KeyPairReqInfo return nil, err } + emptyPermissionList := []string{ + "resources.IID:SystemId", + } + + err = ValidateStruct(reqInfo, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } + cldConn, err := ccm.GetCloudConnection(connectionName) if err != nil { cblog.Error(err) @@ -2104,6 +2177,15 @@ func RegisterVM(connectionName string, userIID cres.IID) (*cres.VMInfo, error) { return nil, err } + emptyPermissionList := []string{ + } + + err = ValidateStruct(userIID, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } + rsType := rsVM cldConn, err := ccm.GetCloudConnection(connectionName) @@ -2191,6 +2273,20 @@ func StartVM(connectionName string, rsType string, reqInfo cres.VMReqInfo) (*cre return nil, err } + emptyPermissionList := []string{ + "resources.IID:SystemId", + "resources.VMReqInfo:RootDiskType", // because can be set without disk type + "resources.VMReqInfo:RootDiskSize", // because can be set without disk type + "resources.VMReqInfo:VMUserId", // because can be set without disk type + "resources.VMReqInfo:VMUserPasswd", // because can be set without disk type + } + + err = ValidateStruct(reqInfo, emptyPermissionList) + if err != nil { + cblog.Error(err) + return nil, err + } + cldConn, err := ccm.GetCloudConnection(connectionName) if err != nil { cblog.Error(err) diff --git a/api-runtime/common-runtime/test/validate_test.go b/api-runtime/common-runtime/test/validate_test.go new file mode 100644 index 000000000..4ed62aba4 --- /dev/null +++ b/api-runtime/common-runtime/test/validate_test.go @@ -0,0 +1,114 @@ +// Mock Driver Test of CB-Spider. +// The CB-Spider is a sub-Framework of the Cloud-Barista Multi-Cloud Project. +// The CB-Spider Mission is to connect all the clouds with a single interface. +// +// * Cloud-Barista: https://github.com/cloud-barista +// +// by CB-Spider Team, 2021.10. + +package validatetest + +import ( + valid "github.com/cloud-barista/cb-spider/api-runtime/common-runtime" + + "testing" + "fmt" +) + +func TestEmpty(t *testing.T) { + + inputValue := "" + + inputValue, err := valid.EmptyCheckAndTrim("inputValue", inputValue) + if err != nil { + fmt.Println(err.Error()) + } + fmt.Printf("Trimed input value: %v.\n", inputValue) +} + +func TestEmptyCheckAndTrim(t *testing.T) { + + inputValue := "inputValue " + + inputValue, err := valid.EmptyCheckAndTrim("inputValue", inputValue) + if err != nil { + fmt.Println(err.Error()) + } + fmt.Printf("Trimed input value: %v.\n", inputValue) +} + +func TestValidate(t *testing.T) { + type InnerTestStruct struct { + Depth2_a string + Depth2_b string + } + + type TestStruct struct { + Depth1_a string + Depth1_b string + Depth1_s *InnerTestStruct + } + + + var ts = TestStruct{ + "name01", + "name02", + &InnerTestStruct{"name03", "name04"}, + } + + err := valid.ValidateStruct(ts, nil) + err = valid.ValidateStruct(&ts, nil) + if err != nil { + fmt.Println(err.Error()) + } +} + +func TestValidateNilByFail(t *testing.T) { + type InnerTestStruct struct { + Depth2_a string + Depth2_b string + } + + type TestStruct struct { + Depth1_a string + Depth1_b string + Depth1_s *InnerTestStruct + } + + + var ts = TestStruct{ + Depth1_a: "name01", + Depth1_s: &InnerTestStruct{"name03", ""}, + } + + err := valid.ValidateStruct(ts, nil) + if err != nil { + fmt.Println(err.Error()) + } +} + +func TestValidateNilByPass(t *testing.T) { + type InnerTestStruct struct { + Depth2_a string + Depth2_b string + } + + type TestStruct struct { + Depth1_a string + Depth1_b string + Depth1_s *InnerTestStruct + } + + + var ts = TestStruct{ + Depth1_a: "name01", + Depth1_s: &InnerTestStruct{"name03", ""}, + } + + err := valid.ValidateStruct(ts, []string{"validatetest.TestStruct:Depth1_b", "validatetest.InnerTestStruct:Depth2_b"}) + if err != nil { + fmt.Println(err.Error()) + } +} + + diff --git a/api-runtime/common-runtime/validator.go b/api-runtime/common-runtime/validator.go index 44177e260..aae28b4db 100644 --- a/api-runtime/common-runtime/validator.go +++ b/api-runtime/common-runtime/validator.go @@ -24,18 +24,31 @@ func EmptyCheckAndTrim(inputName string, inputValue string) (string, error) { return strings.TrimSpace(inputValue), nil } -func ValidateStruct(is interface{}, nilPermissionList []string) error { +func ValidateStruct(is interface{}, emptyPermissionList []string) error { + var retErr error + inValue := reflect.ValueOf(is) if inValue.Kind() == reflect.Ptr { inValue = inValue.Elem() // When Input is ptr of Struct, Get the element. + if inValue.Kind() == reflect.Slice { // When ptr of Array, ex) SecurityRules *[]SecurityRuleInfo + for j := 0; j < inValue.Len(); j++ { + err := ValidateStruct(inValue.Index(j).Interface(), emptyPermissionList) + if retErr != nil { + retErr = fmt.Errorf("%v\n%v", retErr, err) + }else { + retErr = err + } + } + + } } - var retErr error + for i := 0; i < inValue.NumField(); i++ { fv := inValue.Field(i) switch fv.Kind() { case reflect.Struct, reflect.Ptr: - err := ValidateStruct(fv.Interface(), nilPermissionList) + err := ValidateStruct(fv.Interface(), emptyPermissionList) if err != nil { if retErr != nil { retErr = fmt.Errorf("%v\n%v", retErr, err) @@ -45,7 +58,7 @@ func ValidateStruct(is interface{}, nilPermissionList []string) error { } case reflect.Slice: for j := 0; j < fv.Len(); j++ { - err := ValidateStruct(fv.Index(j).Interface(), nilPermissionList) + err := ValidateStruct(fv.Index(j).Interface(), emptyPermissionList) if retErr != nil { retErr = fmt.Errorf("%v\n%v", retErr, err) }else { @@ -58,7 +71,7 @@ func ValidateStruct(is interface{}, nilPermissionList []string) error { //fmt.Println("-----------: " + argNameType) argNameType := fmt.Sprintf("%v:%v", inValue.Type(), inValue.Type().Field(i).Name) if inValue.Field(i).Interface() == "" { - err := checkNilPermission(argNameType, nilPermissionList) + err := checkNilPermission(argNameType, emptyPermissionList) if err != nil { if retErr != nil { retErr = fmt.Errorf("%v\n%v", retErr, err) @@ -69,16 +82,17 @@ func ValidateStruct(is interface{}, nilPermissionList []string) error { } default: - fmt.Println("=========== other type: ", inValue.Field(i).Kind()) + cblog.Info("=========== Currently, Unhandling Type: ", inValue.Field(i).Kind()) + //fmt.Println("=========== other type: ", inValue.Field(i).Kind()) } } return retErr } // Check the arguments that can be used as empty. -func checkNilPermission(argTypeName string, nilPermissionList []string) error { +func checkNilPermission(argTypeName string, emptyPermissionList []string) error { - for _, permittedArgTypeName := range(nilPermissionList) { + for _, permittedArgTypeName := range(emptyPermissionList) { if permittedArgTypeName == argTypeName { return nil }