aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/k8splugin/internal/app/instance.go2
-rw-r--r--src/orchestrator/api/api.go1
-rw-r--r--src/orchestrator/api/app_profilehandler.go4
-rw-r--r--src/orchestrator/api/apphandler.go28
-rw-r--r--src/orchestrator/pkg/infra/validation/validation.go264
-rw-r--r--src/orchestrator/pkg/infra/validation/validation_test.go466
-rw-r--r--src/orchestrator/pkg/module/app.go29
-rw-r--r--src/orchestrator/utils/utils.go66
-rw-r--r--src/orchestrator/utils/utils_test.go74
9 files changed, 789 insertions, 145 deletions
diff --git a/src/k8splugin/internal/app/instance.go b/src/k8splugin/internal/app/instance.go
index 5d8b2100..d6eb91b4 100644
--- a/src/k8splugin/internal/app/instance.go
+++ b/src/k8splugin/internal/app/instance.go
@@ -120,7 +120,7 @@ func NewInstanceClient() *InstanceClient {
}
}
-// Create an entry for the resource bundle profile in the database
+// Create an instance of rb on the cluster in the database
func (v *InstanceClient) Create(i InstanceRequest) (InstanceResponse, error) {
// Name is required
diff --git a/src/orchestrator/api/api.go b/src/orchestrator/api/api.go
index 70b40d96..a261319c 100644
--- a/src/orchestrator/api/api.go
+++ b/src/orchestrator/api/api.go
@@ -84,6 +84,7 @@ func NewRouter(projectClient moduleLib.ProjectManager,
router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{version}/apps", appHandler.createAppHandler).Methods("POST")
router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{version}/apps/{app-name}", appHandler.getAppHandler).Methods("GET")
+ router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{version}/apps", appHandler.getAppHandler).Methods("GET")
router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{version}/apps/{app-name}", appHandler.deleteAppHandler).Methods("DELETE")
if compositeProfileClient == nil {
diff --git a/src/orchestrator/api/app_profilehandler.go b/src/orchestrator/api/app_profilehandler.go
index 16423483..ef7833de 100644
--- a/src/orchestrator/api/app_profilehandler.go
+++ b/src/orchestrator/api/app_profilehandler.go
@@ -27,8 +27,8 @@ import (
"net/http"
"net/textproto"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
- "github.com/onap/multicloud-k8s/src/orchestrator/utils"
"github.com/gorilla/mux"
pkgerrors "github.com/pkg/errors"
@@ -89,7 +89,7 @@ func (h appProfileHandler) createAppProfileHandler(w http.ResponseWriter, r *htt
return
}
- err = utils.IsTarGz(bytes.NewBuffer(content))
+ err = validation.IsTarGz(bytes.NewBuffer(content))
if err != nil {
http.Error(w, "Error in file format", http.StatusUnprocessableEntity)
return
diff --git a/src/orchestrator/api/apphandler.go b/src/orchestrator/api/apphandler.go
index 3cd2dbc8..2c81431c 100644
--- a/src/orchestrator/api/apphandler.go
+++ b/src/orchestrator/api/apphandler.go
@@ -27,8 +27,8 @@ import (
"net/http"
"net/textproto"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/validation"
moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
- "github.com/onap/multicloud-k8s/src/orchestrator/utils"
"github.com/gorilla/mux"
)
@@ -92,7 +92,7 @@ func (h appHandler) createAppHandler(w http.ResponseWriter, r *http.Request) {
return
}
- err = utils.IsTarGz(bytes.NewBuffer(content))
+ err = validation.IsTarGz(bytes.NewBuffer(content))
if err != nil {
http.Error(w, "Error in file format", http.StatusUnprocessableEntity)
return
@@ -129,6 +129,30 @@ func (h appHandler) getAppHandler(w http.ResponseWriter, r *http.Request) {
compositeAppVersion := vars["version"]
name := vars["app-name"]
+ // handle the get all apps case - return a list of only the json parts
+ if len(name) == 0 {
+ var retList []moduleLib.App
+
+ ret, err := h.client.GetApps(projectName, compositeAppName, compositeAppVersion)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ for _, app := range ret {
+ retList = append(retList, moduleLib.App{Metadata: app.Metadata})
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ err = json.NewEncoder(w).Encode(retList)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ return
+ }
+
accepted, _, err := mime.ParseMediaType(r.Header.Get("Accept"))
if err != nil {
http.Error(w, err.Error(), http.StatusNotAcceptable)
diff --git a/src/orchestrator/pkg/infra/validation/validation.go b/src/orchestrator/pkg/infra/validation/validation.go
new file mode 100644
index 00000000..d744dc3d
--- /dev/null
+++ b/src/orchestrator/pkg/infra/validation/validation.go
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2020 Intel Corporation, Inc
+ *
+ * Licensed 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 validation
+
+import (
+ "archive/tar"
+ "compress/gzip"
+ "io"
+ "net"
+ "regexp"
+ "strings"
+
+ pkgerrors "github.com/pkg/errors"
+ "k8s.io/apimachinery/pkg/util/validation"
+)
+
+func IsTarGz(r io.Reader) error {
+ //Check if it is a valid gz
+ gzf, err := gzip.NewReader(r)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Invalid gzip format")
+ }
+
+ //Check if it is a valid tar file
+ //Unfortunately this can only be done by inspecting all the tar contents
+ tarR := tar.NewReader(gzf)
+ first := true
+
+ for true {
+ header, err := tarR.Next()
+
+ if err == io.EOF {
+ //Check if we have just a gzip file without a tar archive inside
+ if first {
+ return pkgerrors.New("Empty or non-existant Tar file found")
+ }
+ //End of archive
+ break
+ }
+
+ if err != nil {
+ return pkgerrors.Errorf("Error reading tar file %s", err.Error())
+ }
+
+ //Check if files are of type directory and regular file
+ if header.Typeflag != tar.TypeDir &&
+ header.Typeflag != tar.TypeReg {
+ return pkgerrors.Errorf("Unknown header in tar %s, %s",
+ header.Name, string(header.Typeflag))
+ }
+
+ first = false
+ }
+
+ return nil
+}
+
+func IsIpv4Cidr(cidr string) error {
+ _, _, err := net.ParseCIDR(cidr)
+ if err != nil {
+ return pkgerrors.Wrapf(err, "could not parse subnet %v", cidr)
+ }
+ return nil
+}
+
+func IsIpv4(ip string) error {
+ addr := net.ParseIP(ip)
+ if addr == nil {
+ return pkgerrors.Errorf("invalid ipv4 address %v", ip)
+ }
+ return nil
+}
+
+// default name check - matches valid label value with addtion that length > 0
+func IsValidName(name string) []string {
+ var errs []string
+
+ errs = validation.IsValidLabelValue(name)
+ if len(name) == 0 {
+ errs = append(errs, "name must have non-zero length")
+ }
+ return errs
+}
+
+const VALID_NAME_STR string = "NAME"
+
+var validNameRegEx = regexp.MustCompile("^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$")
+
+const VALID_ALPHA_STR string = "ALPHA"
+
+var validAlphaStrRegEx = regexp.MustCompile("^[A-Za-z]*$")
+
+const VALID_ALPHANUM_STR string = "ALPHANUM"
+
+var validAlphaNumStrRegEx = regexp.MustCompile("^[A-Za-z0-9]*$")
+
+// doesn't verify valid base64 length - just checks for proper base64 characters
+const VALID_BASE64_STR string = "BASE64"
+
+var validBase64StrRegEx = regexp.MustCompile("^[A-Za-z0-9+/]+={0,2}$")
+
+const VALID_ANY_STR string = "ANY"
+
+var validAnyStrRegEx = regexp.MustCompile("(?s)^.*$")
+
+// string check - validates for conformance to provided lengths and specified content
+// min and max - the string
+// if format string provided - check against matching predefined
+func IsValidString(str string, min, max int, format string) []string {
+ var errs []string
+
+ if min > max {
+ errs = append(errs, "Invalid string length constraints - min is greater than max")
+ return errs
+ }
+
+ if len(str) < min {
+ errs = append(errs, "string length is less than the minimum constraint")
+ return errs
+ }
+ if len(str) > max {
+ errs = append(errs, "string length is greater than the maximum constraint")
+ return errs
+ }
+
+ switch format {
+ case VALID_ALPHA_STR:
+ if !validAlphaStrRegEx.MatchString(str) {
+ errs = append(errs, "string does not match the alpha only constraint")
+ }
+ case VALID_ALPHANUM_STR:
+ if !validAlphaNumStrRegEx.MatchString(str) {
+ errs = append(errs, "string does not match the alphanumeric only constraint")
+ }
+ case VALID_NAME_STR:
+ if !validNameRegEx.MatchString(str) {
+ errs = append(errs, "string does not match the valid k8s name constraint")
+ }
+ case VALID_BASE64_STR:
+ if !validBase64StrRegEx.MatchString(str) {
+ errs = append(errs, "string does not match the valid base64 characters constraint")
+ }
+ if len(str)%4 != 0 {
+ errs = append(errs, "base64 string length should be a multiple of 4")
+ }
+ case VALID_ANY_STR:
+ if !validAnyStrRegEx.MatchString(str) {
+ errs = append(errs, "string does not match the any characters constraint")
+ }
+ default:
+ // invalid string format supplied
+ errs = append(errs, "an invalid string constraint was supplied")
+ }
+
+ return errs
+}
+
+// validate that label conforms to kubernetes label conventions
+// general label format expected is:
+// "<labelprefix>/<labelname>=<Labelvalue>"
+// where labelprefix matches DNS1123Subdomain format
+// labelname matches DNS1123Label format
+//
+// Input labels are allowed to match following formats:
+// "<DNS1123Subdomain>/<DNS1123Label>=<Labelvalue>"
+// "<DNS1123Label>=<LabelValue>"
+// "<LabelValue>"
+func IsValidLabel(label string) []string {
+ var labelerrs []string
+
+ expectLabelName := false
+ expectLabelPrefix := false
+
+ // split label up into prefix, name and value
+ // format: prefix/name=value
+ var labelprefix, labelname, labelvalue string
+
+ kv := strings.SplitN(label, "=", 2)
+ if len(kv) == 1 {
+ labelprefix = ""
+ labelname = ""
+ labelvalue = kv[0]
+ } else {
+ pn := strings.SplitN(kv[0], "/", 2)
+ if len(pn) == 1 {
+ labelprefix = ""
+ labelname = pn[0]
+ } else {
+ labelprefix = pn[0]
+ labelname = pn[1]
+ expectLabelPrefix = true
+ }
+ labelvalue = kv[1]
+ // if "=" was in the label input, then expect a non-zero length name
+ expectLabelName = true
+ }
+
+ // check label prefix validity - prefix is optional
+ if len(labelprefix) > 0 {
+ errs := validation.IsDNS1123Subdomain(labelprefix)
+ if len(errs) > 0 {
+ labelerrs = append(labelerrs, "Invalid label prefix - label=["+label+"%], labelprefix=["+labelprefix+"], errors: ")
+ for _, err := range errs {
+ labelerrs = append(labelerrs, err)
+ }
+ }
+ } else if expectLabelPrefix {
+ labelerrs = append(labelerrs, "Invalid label prefix - label=["+label+"%], labelprefix=["+labelprefix+"]")
+ }
+ if expectLabelName {
+ errs := validation.IsDNS1123Label(labelname)
+ if len(errs) > 0 {
+ labelerrs = append(labelerrs, "Invalid label name - label=["+label+"%], labelname=["+labelname+"], errors: ")
+ for _, err := range errs {
+ labelerrs = append(labelerrs, err)
+ }
+ }
+ }
+ if len(labelvalue) > 0 {
+ errs := validation.IsValidLabelValue(labelvalue)
+ if len(errs) > 0 {
+ labelerrs = append(labelerrs, "Invalid label value - label=["+label+"%], labelvalue=["+labelvalue+"], errors: ")
+ for _, err := range errs {
+ labelerrs = append(labelerrs, err)
+ }
+ }
+ } else {
+ // expect a non-zero value
+ labelerrs = append(labelerrs, "Invalid label value - label=["+label+"%], labelvalue=["+labelvalue+"]")
+ }
+
+ return labelerrs
+}
+
+func IsValidNumber(value, min, max int) []string {
+ var errs []string
+
+ if min > max {
+ errs = append(errs, "invalid constraints")
+ return errs
+ }
+
+ if value < min {
+ errs = append(errs, "value less than minimum")
+ }
+ if value > max {
+ errs = append(errs, "value greater than maximum")
+ }
+ return errs
+}
diff --git a/src/orchestrator/pkg/infra/validation/validation_test.go b/src/orchestrator/pkg/infra/validation/validation_test.go
new file mode 100644
index 00000000..5109b6c7
--- /dev/null
+++ b/src/orchestrator/pkg/infra/validation/validation_test.go
@@ -0,0 +1,466 @@
+/*
+ * Copyright 2018 Intel Corporation, Inc
+ *
+ * Licensed 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 validation
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestIsTarGz(t *testing.T) {
+
+ t.Run("Valid tar.gz", func(t *testing.T) {
+ content := []byte{
+ 0x1f, 0x8b, 0x08, 0x08, 0xb0, 0x6b, 0xf4, 0x5b,
+ 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
+ 0x61, 0x72, 0x00, 0xed, 0xce, 0x41, 0x0a, 0xc2,
+ 0x30, 0x10, 0x85, 0xe1, 0xac, 0x3d, 0x45, 0x4e,
+ 0x50, 0x12, 0xd2, 0xc4, 0xe3, 0x48, 0xa0, 0x01,
+ 0x4b, 0x52, 0x0b, 0xed, 0x88, 0x1e, 0xdf, 0x48,
+ 0x11, 0x5c, 0x08, 0xa5, 0x8b, 0x52, 0x84, 0xff,
+ 0xdb, 0xbc, 0x61, 0x66, 0x16, 0x4f, 0xd2, 0x2c,
+ 0x8d, 0x3c, 0x45, 0xed, 0xc8, 0x54, 0x21, 0xb4,
+ 0xef, 0xb4, 0x67, 0x6f, 0xbe, 0x73, 0x61, 0x9d,
+ 0xb2, 0xce, 0xd5, 0x55, 0xf0, 0xde, 0xd7, 0x3f,
+ 0xdb, 0xd6, 0x49, 0x69, 0xb3, 0x67, 0xa9, 0x8f,
+ 0xfb, 0x2c, 0x71, 0xd2, 0x5a, 0xc5, 0xee, 0x92,
+ 0x73, 0x8e, 0x43, 0x7f, 0x4b, 0x3f, 0xff, 0xd6,
+ 0xee, 0x7f, 0xea, 0x9a, 0x4a, 0x19, 0x1f, 0xe3,
+ 0x54, 0xba, 0xd3, 0xd1, 0x55, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0xbc, 0x00, 0xb5, 0xe8,
+ 0x4a, 0xf9, 0x00, 0x28, 0x00, 0x00,
+ }
+
+ err := IsTarGz(bytes.NewBuffer(content))
+ if err != nil {
+ t.Errorf("Error reading valid tar.gz file %s", err.Error())
+ }
+ })
+
+ t.Run("Invalid tar.gz", func(t *testing.T) {
+ content := []byte{
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xff, 0xf2, 0x48, 0xcd,
+ }
+
+ err := IsTarGz(bytes.NewBuffer(content))
+ if err == nil {
+ t.Errorf("Error should NOT be nil")
+ }
+ })
+
+ t.Run("Empty tar.gz", func(t *testing.T) {
+ content := []byte{}
+ err := IsTarGz(bytes.NewBuffer(content))
+ if err == nil {
+ t.Errorf("Error should NOT be nil")
+ }
+ })
+}
+
+func TestIsValidName(t *testing.T) {
+ t.Run("Valid Names", func(t *testing.T) {
+ validnames := []string{
+ "abc123",
+ "1_abc123.ONE",
+ "0abcABC_-.5",
+ "123456789012345678901234567890123456789012345678901234567890123", // max of 63 characters
+ }
+ for _, name := range validnames {
+ errs := IsValidName(name)
+ if len(errs) > 0 {
+ t.Errorf("Valid name failed to pass: %v", name)
+ }
+ }
+ })
+
+ t.Run("Invalid Names", func(t *testing.T) {
+ invalidnames := []string{
+ "", // empty
+ "_abc123", // starts with non-alphanum
+ "-abc123", // starts with non-alphanum
+ ".abc123", // starts with non-alphanum
+ "abc123-", // ends with non-alphanum
+ "abc123_", // ends with non-alphanum
+ "abc123.", // ends with non-alphanum
+ "1_abc-123.O=NE", // contains not allowed character
+ "1_a/bc-123.ONE", // contains not allowed character
+ "1234567890123456789012345678901234567890123456789012345678901234", // longer than 63 characters
+ }
+ for _, name := range invalidnames {
+ errs := IsValidName(name)
+ if len(errs) == 0 {
+ t.Errorf("Invalid name passed: %v", name)
+ }
+ }
+ })
+}
+
+func TestIsIpv4Cidr(t *testing.T) {
+ t.Run("Valid IPv4 Cidr", func(t *testing.T) {
+ validipv4cidr := []string{
+ "1.2.3.4/32",
+ "10.11.12.0/24",
+ "192.168.1.2/8",
+ "255.0.0.0/16",
+ }
+ for _, ip := range validipv4cidr {
+ err := IsIpv4Cidr(ip)
+ if err != nil {
+ t.Errorf("Valid IPv4 CIDR string failed to pass: %v", ip)
+ }
+ }
+ })
+
+ t.Run("Invalid IPv4 Cidr", func(t *testing.T) {
+ invalidipv4cidr := []string{
+ "",
+ "1.2.3.4.5/32",
+ "1.2.3.415/16",
+ "1.2.3.4/33",
+ "2.3.4/24",
+ "1.2.3.4",
+ "1.2.3.4/",
+ }
+ for _, ip := range invalidipv4cidr {
+ err := IsIpv4Cidr(ip)
+ if err == nil {
+ t.Errorf("Invalid IPv4 Cidr passed: %v", ip)
+ }
+ }
+ })
+}
+
+func TestIsIpv4(t *testing.T) {
+ t.Run("Valid IPv4", func(t *testing.T) {
+ validipv4 := []string{
+ "1.2.3.42",
+ "10.11.12.0",
+ "192.168.1.2",
+ "255.0.0.0",
+ "255.255.255.255",
+ "0.0.0.0",
+ }
+ for _, ip := range validipv4 {
+ err := IsIpv4(ip)
+ if err != nil {
+ t.Errorf("Valid IPv4 string failed to pass: %v", ip)
+ }
+ }
+ })
+
+ t.Run("Invalid IPv4", func(t *testing.T) {
+ invalidipv4 := []string{
+ "",
+ "1.2.3.4.5",
+ "1.2.3.45/32",
+ "1.2.3.4a",
+ "2.3.4",
+ "1.2.3.400",
+ "256.255.255.255",
+ "10,11,12,13",
+ "1.2.3.4/",
+ }
+ for _, ip := range invalidipv4 {
+ err := IsIpv4(ip)
+ if err == nil {
+ t.Errorf("Invalid IPv4 passed: %v", ip)
+ }
+ }
+ })
+}
+
+func TestIsValidString(t *testing.T) {
+ t.Run("Valid Strings", func(t *testing.T) {
+ validStrings := []struct {
+ str string
+ min int
+ max int
+ format string
+ }{
+ {
+ str: "abc123",
+ min: 0,
+ max: 16,
+ format: VALID_NAME_STR,
+ },
+ {
+ str: "ab-c1_2.3",
+ min: 0,
+ max: 16,
+ format: VALID_NAME_STR,
+ },
+ {
+ str: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ min: 0,
+ max: 62,
+ format: VALID_ALPHANUM_STR,
+ },
+ {
+ str: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ min: 0,
+ max: 52,
+ format: VALID_ALPHA_STR,
+ },
+ {
+ str: "",
+ min: 0,
+ max: 52,
+ format: VALID_ALPHA_STR,
+ },
+ {
+ str: "",
+ min: 0,
+ max: 52,
+ format: VALID_ALPHANUM_STR,
+ },
+ {
+ str: "dGhpcyBpcyBhCnRlc3Qgc3RyaW5nCg==",
+ min: 0,
+ max: 52,
+ format: VALID_BASE64_STR,
+ },
+ {
+ str: "\t\n \n0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+-=,.<>/?'\"\\[]{}\n",
+ min: 0,
+ max: 256,
+ format: VALID_ANY_STR,
+ },
+ }
+ for _, test := range validStrings {
+ errs := IsValidString(test.str, test.min, test.max, test.format)
+ if len(errs) > 0 {
+ t.Errorf("Valid string failed to pass: str:%v, min:%v, max:%v, format:%v", test.str, test.min, test.max, test.format)
+ }
+ }
+ })
+
+ t.Run("Invalid Strings", func(t *testing.T) {
+ inValidStrings := []struct {
+ str string
+ min int
+ max int
+ format string
+ }{
+ {
+ str: "abc123",
+ min: 0,
+ max: 5,
+ format: VALID_NAME_STR,
+ },
+ {
+ str: "",
+ min: 0,
+ max: 5,
+ format: VALID_NAME_STR,
+ },
+ {
+ str: "-ab-c1_2.3",
+ min: 0,
+ max: 16,
+ format: VALID_NAME_STR,
+ },
+ {
+ str: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ=",
+ min: 0,
+ max: 100,
+ format: VALID_ALPHANUM_STR,
+ },
+ {
+ str: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456",
+ min: 0,
+ max: 62,
+ format: VALID_ALPHA_STR,
+ },
+ {
+ str: "",
+ min: 1,
+ max: 52,
+ format: VALID_ALPHA_STR,
+ },
+ {
+ str: "abc123",
+ min: 1,
+ max: 3,
+ format: VALID_ALPHA_STR,
+ },
+ {
+ str: "",
+ min: 1,
+ max: 52,
+ format: VALID_ALPHANUM_STR,
+ },
+ {
+ str: "dGhpcyBpcyBhCnRlc3Qgc3RyaW5nCg===",
+ min: 0,
+ max: 52,
+ format: VALID_BASE64_STR,
+ },
+ {
+ str: "dGhpcyBpcyBhCnRlc3=Qgc3RyaW5nCg==",
+ min: 0,
+ max: 52,
+ format: VALID_BASE64_STR,
+ },
+ {
+ str: "dGhpcyBpcyBhCnRlc3#Qgc3RyaW5nCg==",
+ min: 0,
+ max: 52,
+ format: VALID_BASE64_STR,
+ },
+ {
+ str: "\t\n \n0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+-=,.<>/?'\"\\[]{}\n",
+ min: 0,
+ max: 10,
+ format: VALID_ANY_STR,
+ },
+ {
+ str: "abc123",
+ min: 0,
+ max: 10,
+ format: "unknownformat",
+ },
+ }
+ for _, test := range inValidStrings {
+ errs := IsValidString(test.str, test.min, test.max, test.format)
+ if len(errs) == 0 {
+ t.Errorf("Invalid string passed: str:%v, min:%v, max:%v, format:%v", test.str, test.min, test.max, test.format)
+ }
+ }
+ })
+}
+
+func TestIsValidLabel(t *testing.T) {
+ t.Run("Valid Labels", func(t *testing.T) {
+ validlabels := []string{
+ "kubernetes.io/hostname=localhost",
+ "hostname=localhost",
+ "localhost",
+ }
+ for _, label := range validlabels {
+ errs := IsValidLabel(label)
+ if len(errs) > 0 {
+ t.Errorf("Valid label failed to pass: %v %v", label, errs)
+ }
+ }
+ })
+
+ t.Run("Invalid Labels", func(t *testing.T) {
+ invalidlabels := []string{
+ "",
+ "kubernetes$.io/hostname=localhost",
+ "hostname==localhost",
+ "=localhost",
+ "/hostname=localhost",
+ ".a.b/hostname=localhost",
+ "kubernetes.io/hostname",
+ "kubernetes.io/hostname=",
+ "kubernetes.io/1234567890123456789012345678901234567890123456789012345678901234=localhost", // too long name
+ "kubernetes.io/hostname=localhost1234567890123456789012345678901234567890123456789012345678901234", // too long value
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234/hostname=localhost", // too long prefix
+ }
+ for _, label := range invalidlabels {
+ errs := IsValidLabel(label)
+ if len(errs) == 0 {
+ t.Errorf("Invalid label passed: %v", label)
+ }
+ }
+ })
+}
+
+func TestIsValidNumber(t *testing.T) {
+ t.Run("Valid Number", func(t *testing.T) {
+ validNumbers := []struct {
+ value int
+ min int
+ max int
+ }{
+ {
+ value: 0,
+ min: 0,
+ max: 5,
+ },
+ {
+ value: 1000,
+ min: 0,
+ max: 4095,
+ },
+ {
+ value: 0,
+ min: 0,
+ max: 0,
+ },
+ {
+ value: -100,
+ min: -200,
+ max: -99,
+ },
+ {
+ value: 123,
+ min: 123,
+ max: 123,
+ },
+ }
+ for _, test := range validNumbers {
+ err := IsValidNumber(test.value, test.min, test.max)
+ if len(err) > 0 {
+ t.Errorf("Valid number failed to pass - value:%v, min:%v, max:%v", test.value, test.min, test.max)
+ }
+ }
+ })
+
+ t.Run("Invalid Number", func(t *testing.T) {
+ inValidNumbers := []struct {
+ value int
+ min int
+ max int
+ }{
+ {
+ value: 6,
+ min: 0,
+ max: 5,
+ },
+ {
+ value: 4096,
+ min: 0,
+ max: 4095,
+ },
+ {
+ value: 11,
+ min: 10,
+ max: 10,
+ },
+ {
+ value: -100,
+ min: -99,
+ max: -200,
+ },
+ {
+ value: 123,
+ min: 223,
+ max: 123,
+ },
+ }
+ for _, test := range inValidNumbers {
+ err := IsValidNumber(test.value, test.min, test.max)
+ if len(err) == 0 {
+ t.Errorf("Invalid number passed - value:%v, min:%v, max:%v", test.value, test.min, test.max)
+ }
+ }
+ })
+}
diff --git a/src/orchestrator/pkg/module/app.go b/src/orchestrator/pkg/module/app.go
index c25a1b51..1e1a5974 100644
--- a/src/orchestrator/pkg/module/app.go
+++ b/src/orchestrator/pkg/module/app.go
@@ -65,6 +65,7 @@ type AppManager interface {
CreateApp(a App, ac AppContent, p string, cN string, cV string) (App, error)
GetApp(name string, p string, cN string, cV string) (App, error)
GetAppContent(name string, p string, cN string, cV string) (AppContent, error)
+ GetApps(p string, cN string, cV string) ([]App, error)
DeleteApp(name string, p string, cN string, cV string) error
}
@@ -183,6 +184,34 @@ func (v *AppClient) GetAppContent(name string, p string, cN string, cV string) (
return AppContent{}, pkgerrors.New("Error getting app content")
}
+// GetApps returns all Apps for given composite App
+func (v *AppClient) GetApps(project, compositeApp, compositeAppVersion string) ([]App, error) {
+
+ key := AppKey{
+ App: "",
+ Project: project,
+ CompositeApp: compositeApp,
+ CompositeAppVersion: compositeAppVersion,
+ }
+
+ var resp []App
+ values, err := db.DBconn.Find(v.storeName, key, v.tagMeta)
+ if err != nil {
+ return []App{}, pkgerrors.Wrap(err, "Get Apps")
+ }
+
+ for _, value := range values {
+ a := App{}
+ err = db.DBconn.Unmarshal(value, &a)
+ if err != nil {
+ return []App{}, pkgerrors.Wrap(err, "Unmarshaling Value")
+ }
+ resp = append(resp, a)
+ }
+
+ return resp, nil
+}
+
// DeleteApp deletes the App from database
func (v *AppClient) DeleteApp(name string, p string, cN string, cV string) error {
diff --git a/src/orchestrator/utils/utils.go b/src/orchestrator/utils/utils.go
deleted file mode 100644
index 44cf5120..00000000
--- a/src/orchestrator/utils/utils.go
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2020 Intel Corporation, Inc
- *
- * Licensed 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 utils
-
-import (
- "archive/tar"
- "compress/gzip"
- "io"
-
- pkgerrors "github.com/pkg/errors"
-)
-
-func IsTarGz(r io.Reader) error {
- //Check if it is a valid gz
- gzf, err := gzip.NewReader(r)
- if err != nil {
- return pkgerrors.Wrap(err, "Invalid gzip format")
- }
-
- //Check if it is a valid tar file
- //Unfortunately this can only be done by inspecting all the tar contents
- tarR := tar.NewReader(gzf)
- first := true
-
- for true {
- header, err := tarR.Next()
-
- if err == io.EOF {
- //Check if we have just a gzip file without a tar archive inside
- if first {
- return pkgerrors.New("Empty or non-existant Tar file found")
- }
- //End of archive
- break
- }
-
- if err != nil {
- return pkgerrors.Errorf("Error reading tar file %s", err.Error())
- }
-
- //Check if files are of type directory and regular file
- if header.Typeflag != tar.TypeDir &&
- header.Typeflag != tar.TypeReg {
- return pkgerrors.Errorf("Unknown header in tar %s, %s",
- header.Name, string(header.Typeflag))
- }
-
- first = false
- }
-
- return nil
-}
diff --git a/src/orchestrator/utils/utils_test.go b/src/orchestrator/utils/utils_test.go
deleted file mode 100644
index 63230e49..00000000
--- a/src/orchestrator/utils/utils_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2018 Intel Corporation, Inc
- *
- * Licensed 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 utils
-
-import (
- "bytes"
- "testing"
-)
-
-func TestIsTarGz(t *testing.T) {
-
- t.Run("Valid tar.gz", func(t *testing.T) {
- content := []byte{
- 0x1f, 0x8b, 0x08, 0x08, 0xb0, 0x6b, 0xf4, 0x5b,
- 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
- 0x61, 0x72, 0x00, 0xed, 0xce, 0x41, 0x0a, 0xc2,
- 0x30, 0x10, 0x85, 0xe1, 0xac, 0x3d, 0x45, 0x4e,
- 0x50, 0x12, 0xd2, 0xc4, 0xe3, 0x48, 0xa0, 0x01,
- 0x4b, 0x52, 0x0b, 0xed, 0x88, 0x1e, 0xdf, 0x48,
- 0x11, 0x5c, 0x08, 0xa5, 0x8b, 0x52, 0x84, 0xff,
- 0xdb, 0xbc, 0x61, 0x66, 0x16, 0x4f, 0xd2, 0x2c,
- 0x8d, 0x3c, 0x45, 0xed, 0xc8, 0x54, 0x21, 0xb4,
- 0xef, 0xb4, 0x67, 0x6f, 0xbe, 0x73, 0x61, 0x9d,
- 0xb2, 0xce, 0xd5, 0x55, 0xf0, 0xde, 0xd7, 0x3f,
- 0xdb, 0xd6, 0x49, 0x69, 0xb3, 0x67, 0xa9, 0x8f,
- 0xfb, 0x2c, 0x71, 0xd2, 0x5a, 0xc5, 0xee, 0x92,
- 0x73, 0x8e, 0x43, 0x7f, 0x4b, 0x3f, 0xff, 0xd6,
- 0xee, 0x7f, 0xea, 0x9a, 0x4a, 0x19, 0x1f, 0xe3,
- 0x54, 0xba, 0xd3, 0xd1, 0x55, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x1b, 0xbc, 0x00, 0xb5, 0xe8,
- 0x4a, 0xf9, 0x00, 0x28, 0x00, 0x00,
- }
-
- err := IsTarGz(bytes.NewBuffer(content))
- if err != nil {
- t.Errorf("Error reading valid tar.gz file %s", err.Error())
- }
- })
-
- t.Run("Invalid tar.gz", func(t *testing.T) {
- content := []byte{
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xf2, 0x48, 0xcd,
- }
-
- err := IsTarGz(bytes.NewBuffer(content))
- if err == nil {
- t.Errorf("Error should NOT be nil")
- }
- })
-
- t.Run("Empty tar.gz", func(t *testing.T) {
- content := []byte{}
- err := IsTarGz(bytes.NewBuffer(content))
- if err == nil {
- t.Errorf("Error should NOT be nil")
- }
- })
-}