diff options
36 files changed, 1905 insertions, 145 deletions
diff --git a/kud/tests/_common.sh b/kud/tests/_common.sh index 92c09b0d..cd704c53 100755 --- a/kud/tests/_common.sh +++ b/kud/tests/_common.sh @@ -1158,3 +1158,15 @@ function populate_CSAR_fw_rbdefinition { popd } +function populate_CSAR_composite_app_helm { + _checks_args "$1" + pushd "${CSAR_DIR}/$1" + print_msg "Create Helm Chart Archives for compositeApp" + rm -f *.tar.gz + tar -czf collectd.tar.gz -C $test_folder/vnfs/comp-app/collection/app1/helm . + tar -czf prometheus.tar.gz -C $test_folder/vnfs/comp-app/collection/app2/helm . + tar -czf collectd_profile.tar.gz -C $test_folder/vnfs/comp-app/collection/app1/profile . + tar -czf prometheus_profile.tar.gz -C $test_folder/vnfs/comp-app/collection/app2/profile . + popd +} + diff --git a/kud/tests/plugin_collection_v2.sh b/kud/tests/plugin_collection_v2.sh new file mode 100755 index 00000000..068864d7 --- /dev/null +++ b/kud/tests/plugin_collection_v2.sh @@ -0,0 +1,392 @@ +# /* +# * 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. +# */ + +set -o errexit +set -o nounset +set -o pipefail +#set -o xtrace + +source _common_test.sh +source _functions.sh +source _common.sh + +if [ ${1:+1} ]; then + if [ "$1" == "--external" ]; then + master_ip=$(kubectl cluster-info | grep "Kubernetes master" | \ + awk -F ":" '{print $2}' | awk -F "//" '{print $2}') + onap_svc_node_port=30498 + base_url="http://$master_ip:$onap_svc_node_port/v1" + fi +fi + +base_url=${base_url:-"http://localhost:9015/v2"} +kubeconfig_path="$HOME/.kube/config" +csar_id=cb009bfe-bbee-11e8-9766-525400435678 + + +project_name="test_project" +project_description="test_project_description" +userData1="user1" +userData2="user2" + +composite_app_name="test_composite_app" +composite_app_description="test_project_description" +composite_app_version="test_composite_app_version" +app1_helm_path="$CSAR_DIR/$csar_id/collectd.tar.gz" +app2_helm_path="$CSAR_DIR/$csar_id/prometheus.tar.gz" +app1_profile_path="$CSAR_DIR/$csar_id/collectd_profile.tar.gz" +app2_profile_path="$CSAR_DIR/$csar_id/prometheus_profile.tar.gz" + +app1_name="collectd" +app2_name="prometheus" +app1_desc="collectd_desc" +app2_desc="prometheus_desc" + +main_composite_profile_name="main_composite_profile" +sub_composite_profile_name1="test_composite_profile1" +sub_composite_profile_name2="test_composite_profile2" +composite_profile_description="test_composite_profile_description" + +genericPlacementIntentName1="test_gen_placement_intent1" +genericPlacementIntentName2="test_gen_placement_intent2" +genericPlacementIntentDesc="test_gen_placement_intent_desc" +logicalCloud="logical_cloud_name" +clusterName1="edge1" +clusterName2="edge2" +clusterLabelName1="east-us1" +clusterLabelName2="east-us2" + +deploymentIntentGroupName="test_deployment_intent_group" +deploymentIntentGroupNameDesc="test_deployment_intent_group_desc" + +chart_name="edgex" +profile_name="test_profile" +release_name="test-release" +namespace="plugin-tests-namespace" +cloud_region_id="kud" +cloud_region_owner="localhost" + +# Setup +install_deps +populate_CSAR_composite_app_helm "$csar_id" + +# BEGIN: Register project API +print_msg "Registering project" +payload="$(cat <<EOF +{ + "metadata": { + "name": "${project_name}", + "description": "${project_description}", + "userData1": "${userData1}", + "userData2": "${userData2}" + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects" +# END: Register project API + +# BEGIN: Register composite-app API +print_msg "Registering composite-app" +payload="$(cat <<EOF +{ + "metadata": { + "name": "${composite_app_name}", + "description": "${composite_app_description}", + "userData1": "${userData1}", + "userData2": "${userData2}" + }, + "spec":{ + "version":"${composite_app_version}" + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps" +# END: Register composite-app API + + + + +# BEGIN: Create entries for app1&app2 in the database +print_msg "Making app entry in the database" +payload="$(cat <<EOF +{ + "metadata": { + "name": "${app1_name}", + "description": "${app1_desc}", + "userData1": "${userData1}", + "userData2": "${userData2}" + } +} +EOF +)" + +call_api -F "metadata=$payload" \ + -F "file=@$app1_helm_path" \ + "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/apps" + + +# BEGIN: Create an entry for app2 in the database +print_msg "Making app entry in the database" +payload="$(cat <<EOF +{ + "metadata": { + "name": "${app2_name}", + "description": "${app2_desc}", + "userData1": "${userData1}", + "userData2": "${userData2}" + } +} +EOF +)" + +call_api -F "metadata=$payload" \ + -F "file=@$app2_helm_path" \ + "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/apps" +# END: Create entries for app1&app2 in the database + + +# BEGIN: Register the main composite-profile +print_msg "Registering the main composite-profile" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${main_composite_profile_name}", + "description":"${composite_profile_description}", + "userData1":"${userData1}", + "userData2":"${userData2}" + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/composite-profiles" +# BEGIN: Register the main composite-profile + + +# BEGIN : Adding profile to each of the two apps - app1(collectd) and app2(prometheus) +print_msg "Registering profile with app1(collectd)" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${sub_composite_profile_name1}", + "description":"${composite_profile_description}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "app-name": "${app1_name}" + } +} +EOF +)" + +call_api -F "metadata=$payload" \ + -F "file=@$app1_profile_path" \ + "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/composite-profiles/${main_composite_profile_name}/profiles" + +print_msg "Registering profile with app2(prometheus)" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${sub_composite_profile_name2}", + "description":"${composite_profile_description}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "app-name": "${app2_name}" + } +} +EOF +)" + +call_api -F "metadata=$payload" \ + -F "file=@$app2_profile_path" \ + "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/composite-profiles/${main_composite_profile_name}/profiles" +# END : Adding profile to each of the two apps - app1(collectd) and app2(prometheus) + +# BEGIN: Register GenericPlacementIntents with the database +print_msg "Registering GenericPlacementIntent for app1" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${genericPlacementIntentName1}", + "description":"${genericPlacementIntentDesc}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "logical-cloud":"${logicalCloud}" + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/generic-placement-intents" + + +print_msg "Registering GenericPlacementIntent for app2" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${genericPlacementIntentName2}", + "description":"${genericPlacementIntentDesc}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "logical-cloud":"${logicalCloud}" + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/generic-placement-intents" +# END: Register GenericPlacementIntents with the database + +# BEGIN: Adding placement intent for each app in the composite app. +print_msg "Adding placement intent for app1(collectd)" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${genericPlacementIntentName1}", + "description":"${genericPlacementIntentDesc}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "app-name":"${app1_name}", + "intent":{ + "allOf":[ + { + "cluster-name":"${clusterName1}" + }, + { + "cluster-name":"${clusterName2}" + }, + { + "anyOf":[ + { + "cluster-label-name":"${clusterLabelName1}" + }, + { + "cluster-label-name":"${clusterLabelName2}" + } + ] + } + ] + } + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/generic-placement-intents/${genericPlacementIntentName1}/app-intents" + +print_msg "Adding placement intent for app2(prometheus)" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${genericPlacementIntentName2}", + "description":"${genericPlacementIntentDesc}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "app-name":"${app2_name}", + "intent":{ + "allOf":[ + { + "cluster-name":"${clusterName1}" + }, + { + "cluster-name":"${clusterName2}" + }, + { + "anyOf":[ + { + "cluster-label-name":"${clusterLabelName1}" + }, + { + "cluster-label-name":"${clusterLabelName2}" + } + ] + } + ] + } + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/generic-placement-intents/${genericPlacementIntentName2}/app-intents" +# END: Adding placement intent for each app in the composite app. + +# BEGIN: Registering DeploymentIntentGroup in the database +print_msg "Registering DeploymentIntentGroup" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${deploymentIntentGroupName}", + "description":"${deploymentIntentGroupNameDesc}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "profile":"${main_composite_profile_name}", + "version":"${composite_app_version}", + "override-values":[ + { + "app-name":"${app1_name}", + "values": + { + "imageRepository":"registry.hub.docker.com" + } + }, + { + "app-name":"${app2_name}", + "values": + { + "imageRepository":"registry.hub.docker.com" + } + } + ] + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/deployment-intent-groups" +# END: Registering DeploymentIntentGroup in the database + +# BEGIN: Adding intents to an intent group +print_msg "Adding two intents to the intent group" +payload="$(cat <<EOF +{ + "metadata":{ + "name":"${deploymentIntentGroupName}", + "description":"${deploymentIntentGroupNameDesc}", + "userData1":"${userData1}", + "userData2":"${userData2}" + }, + "spec":{ + "intent":{ + "generic-placement-intent":"${genericPlacementIntentName1}", + "generic-placement-intent":"${genericPlacementIntentName2}" + } + } +} +EOF +)" +call_api -d "${payload}" "${base_url}/projects/${project_name}/composite-apps/${composite_app_name}/${composite_app_version}/deployment-intent-groups/${deploymentIntentGroupName}/intents" +# END: Adding intents to an intent group + diff --git a/kud/tests/vnfs/comp-app/collection/.helmignore b/kud/tests/vnfs/comp-app/collection/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/.helmignore b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/.helmignore new file mode 100644 index 00000000..f0c13194 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/Chart.yaml b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/Chart.yaml new file mode 100644 index 00000000..fcdcfde9 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/Chart.yaml @@ -0,0 +1,19 @@ +# Copyright 2019 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. + +apiVersion: v1 +appVersion: "7.1.0" +description: Collectd Helm Chart +name: collectd +version: 0.2.0 diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/resources/collectd.conf b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/resources/collectd.conf new file mode 100644 index 00000000..b023b320 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/resources/collectd.conf @@ -0,0 +1,44 @@ +FQDNLookup false +LoadPlugin cpu +LoadPlugin memory +LoadPlugin cpufreq +LoadPlugin disk +LoadPlugin ethstat +LoadPlugin ipc +LoadPlugin ipmi +LoadPlugin load +LoadPlugin numa +LoadPlugin processes +LoadPlugin df +LoadPlugin turbostat +LoadPlugin uptime +LoadPlugin contextswitch +LoadPlugin irq +LoadPlugin df +LoadPlugin swap +LoadPlugin write_prometheus + +LoadPlugin logfile +<Plugin logfile> + LogLevel info + File "/var/log/collectd.log" + Timestamp true + PrintSeverity false +</Plugin> +<Plugin "cpu"> + Interval 5 + ReportByState false + ReportByCpu false +</Plugin> + +<Plugin "memory"> + Interval 30 + ValuesAbsolute false + ValuesPercentage true +</Plugin> + +<Plugin "write_prometheus"> + Port "{{ .Values.collectd_prometheus.service.targetPort }}" +</Plugin> + +#Last line (collectd requires ā\nā at the last line) diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/NOTES.txt b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/NOTES.txt new file mode 100644 index 00000000..06ca128b --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/NOTES.txt @@ -0,0 +1,34 @@ +# Copyright (c) 2019 Intel Corporation. +# +# 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. + + +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http://{{ . }} +{{- end }} +{{- else if contains "NodePort" .Values.collectd_prometheus.service.type }} + NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "name" . }}) + NODE_IPS=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[*].status.addresses[0].address}") + visit http://NODE_IP:NODE_PORT +{{- else if contains "LoadBalancer" .Values.collectd_prometheus.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ include "name" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "name" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.externalPort }} +{{- else if contains "ClusterIP" .Values.collectd_prometheus.service.type }} + CLUSTER_NODE_IPS=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[*].status.addresses[0].address}") + CLUSTER_NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].port}" services {{ include "name" . }}) + visit http://CLUSTER_NODE_IP:CLUSTER_NODE_PORT +{{- end }} diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/_helpers.tpl b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/_helpers.tpl new file mode 100644 index 00000000..b5e98086 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/_helpers.tpl @@ -0,0 +1,25 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* Workaround for https://github.com/helm/helm/issues/3117 */}} +{{- define "rangeskipempty" -}} +{{- range $key, $value := . }} +{{- if $value }} +{{ $key }}: {{ $value }} +{{- end }} +{{- end }} +{{- end }}
\ No newline at end of file diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/configmap.yaml b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/configmap.yaml new file mode 100644 index 00000000..26d0fb5d --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/configmap.yaml @@ -0,0 +1,26 @@ +{{/* +# Copyright 2019 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. +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "fullname" . }}-config + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} +data: + {{- tpl (.Files.Glob "resources/*").AsConfig . | nindent 2 }} diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/daemonset.yaml b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/daemonset.yaml new file mode 100644 index 00000000..bc686381 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/daemonset.yaml @@ -0,0 +1,84 @@ +{{/* +# Copyright 2019 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. +*/}} + +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: {{ template "fullname" . }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + app: {{ template "name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} +spec: + replicas: {{ .Values.replicaCount }} + updateStrategy: + type: RollingUpdate + template: + metadata: + labels: + app: {{ template "name" . }} + collector: collectd + release: {{ .Release.Name }} + spec: + hostNetwork: true + {{- if .Values.serviceAccountName }} + serviceAccountName: {{ .Values.serviceAccountName }} + {{- end }} +{{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | trim | indent 8 }} +{{- end }} +{{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | trim | indent 8 }} +{{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + allowPrivilegeEscalation: true + privileged: true +{{- if .Values.env }} + env: +{{ toYaml .Values.env | trim | indent 10 }} +{{- end }} +{{- if .Values.command }} + command: +{{ toYaml .Values.command | trim | indent 10 }} +{{- end }} +{{- if .Values.args }} + args: +{{ toYaml .Values.args | trim | indent 10 }} +{{- end }} + volumeMounts: + - name: {{ template "fullname" . }}-config + mountPath: {{ .Values.configMountPath }} +{{- if .Values.volumeMounts }} +{{ toYaml .Values.volumeMounts | trim | indent 10 }} +{{- end }} + resources: +{{- toYaml .Values.resources | trim | indent 12}} + volumes: + - name: {{ template "fullname" . }}-config + configMap: + name: {{ template "fullname" . }}-config + defaultMode: 0744 +{{- if .Values.volumeMounts }} +{{ toYaml .Values.volumes | indent 6 }} +{{- end }} diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/service.yaml b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/service.yaml new file mode 100644 index 00000000..7571715d --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/templates/service.yaml @@ -0,0 +1,32 @@ +{{/* +# Copyright 2019 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. +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: collectd + labels: + app: collectd + release: {{ .Release.Name }} +spec: + ports: + - name: collectd-prometheus + port: {{ .Values.collectd_prometheus.service.port }} + protocol: TCP + targetPort: {{ .Values.collectd_prometheus.service.targetPort }} + selector: +{{ include "rangeskipempty" .Values.collectd_prometheus.service.selector | indent 4 }} + type: ClusterIP diff --git a/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/values.yaml b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/values.yaml new file mode 100644 index 00000000..41d63cbf --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/helm/collectd/values.yaml @@ -0,0 +1,78 @@ +# Default values for collectd. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +ingress: + enabled: false +image: + repository: opnfv/barometer-collectd + tag: latest + pullPolicy: IfNotPresent +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + +#serviceAccountName: cmk-serviceaccount + +# Uncomment the following tolerations and/or nodeSelector to select the node collectd to be deployed +#tolerations: +# - operator: "Exists" +#nodeSelector: +# vcmts: "true" + +# Uncomment the following to set environment, command and args for the collectd container +#env: +#- name: CMK_PROC_FS +# value: "/host/proc" +#command: +#- "/bin/bash" +#- "-c" +#args: [ "/opt/bin/cmk isolate --conf-dir=/etc/cmk --pool=infra /script/collectd.sh" ] + +# all the files under the directory resource will be mount into the directory specified by 'configMountPath' inside the container. +# Besides that, users can specify any mount by using the 'volumeMounts' and 'volumes'. +configMountPath: /opt/collectd/etc +volumeMounts: +- name: proc + mountPath: /mnt/proc + readOnly: true +- name: root + mountPath: /hostfs + readOnly: true +- name: etc + mountPath: /mnt/etc + readOnly: true +- name: run + mountPath: /var/run/docker.sock + +volumes: +- name: proc + hostPath: + path: /proc +- name: root + hostPath: + path: / +- name: etc + hostPath: + path: /etc +- name: run + hostPath: + path: /var/run/docker.sock + +collectd_prometheus: + service: + type: ClusterIP + name: collectd + port: 9103 + targetPort: 9103 + selector: + app: collectd + collector: collectd diff --git a/kud/tests/vnfs/comp-app/collection/app1/profile/manifest.yaml b/kud/tests/vnfs/comp-app/collection/app1/profile/manifest.yaml new file mode 100644 index 00000000..4d381d02 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/profile/manifest.yaml @@ -0,0 +1,4 @@ +--- +version: v1 +type: + values: "override_values.yaml" diff --git a/kud/tests/vnfs/comp-app/collection/app1/profile/override_values.yaml b/kud/tests/vnfs/comp-app/collection/app1/profile/override_values.yaml new file mode 100644 index 00000000..304ae5de --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app1/profile/override_values.yaml @@ -0,0 +1,9 @@ +collectd_prometheus: + service: + type: ClusterIP + name: collectd-override + port: 9103 + targetPort: 9103 + selector: + app: collectd + collector: collectd
\ No newline at end of file diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/.helmignore b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/.helmignore new file mode 100644 index 00000000..50af0317 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/.helmignore @@ -0,0 +1,22 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/Chart.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/Chart.yaml new file mode 100644 index 00000000..6e7ddfbc --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: Prometheus instance with remote storage integrations. +name: prometheus +version: 0.1.0 diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/NOTES.txt b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/NOTES.txt new file mode 100644 index 00000000..f8882883 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/NOTES.txt @@ -0,0 +1,15 @@ +1. Get the application URL by running these commands: +{{ if contains "NodePort" .Values.prometheus.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "prometheus.fullname" . }}-prometheus) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.prometheus.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ include "prometheus.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "prometheus.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.prometheus.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "prometheus.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:9090 to use your application" + kubectl port-forward $POD_NAME 9090:80 +{{- end }} diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/_helpers.tpl b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/_helpers.tpl new file mode 100644 index 00000000..17b7e7bd --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/_helpers.tpl @@ -0,0 +1,57 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prometheus.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "prometheus.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prometheus.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* Create chart name and version as used by the chart label. */}} +{{- define "prometheus.chartref" -}} +{{- replace "+" "_" .Chart.Version | printf "%s-%s" .Chart.Name -}} +{{- end }} + +{{/* Generate basic labels */}} +{{- define "prometheus.labels" }} +chart: {{ template "prometheus.chartref" . }} +release: {{ .Release.Name | quote }} +heritage: {{ .Release.Service | quote }} +{{- if .Values.commonLabels}} +{{ toYaml .Values.commonLabels }} +{{- end }} +{{- end }} + + +{{/* Create the name of prometheus service account to use */}} +{{- define "prometheus.serviceAccountName" -}} +{{- if .Values.prometheus.serviceAccount.create -}} + {{ default (include "prometheus.fullname" .) .Values.prometheus.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.prometheus.serviceAccount.name }} +{{- end -}} +{{- end -}}
\ No newline at end of file diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/prometheus.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/prometheus.yaml new file mode 100644 index 00000000..53494920 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/prometheus.yaml @@ -0,0 +1,19 @@ +apiVersion: monitoring.coreos.com/v1 +kind: Prometheus +metadata: + name: {{ template "prometheus.fullname" . }}-prometheus + labels: + app: {{ template "prometheus.name" . }}-prometheus + "helm.sh/hook": post-install + "helm.sh/hook-weight": "2" +spec: + serviceAccountName: {{ template "prometheus.serviceAccountName" . }} + serviceMonitorSelector: + matchLabels: + app: {{ template "prometheus.name" . }}-prometheus + release: {{ .Release.Name }} + serviceMonitorNamespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + resources: +{{ toYaml .Values.prometheus.resources | indent 4 }} diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/role.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/role.yaml new file mode 100644 index 00000000..dfb932d8 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/role.yaml @@ -0,0 +1,21 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "prometheus.fullname" . }}-prometheus + labels: + app: {{ template "prometheus.name" . }}-prometheus +{{ include "prometheus.labels" . | indent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + - services + - endpoints + - pods + verbs: + - get + - list + - watch
\ No newline at end of file diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/rolebinding.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/rolebinding.yaml new file mode 100644 index 00000000..04932ee1 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/rolebinding.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "prometheus.fullname" . }}-prometheus + labels: + app: {{ template "prometheus.name" . }}-prometheus +{{ include "prometheus.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "prometheus.fullname" . }}-prometheus +subjects: +- kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName" . }} + namespace: {{ .Release.Namespace }}
\ No newline at end of file diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/service.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/service.yaml new file mode 100644 index 00000000..0114ed2e --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/service.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "prometheus.fullname" . }}-prometheus + labels: + app: {{ template "prometheus.name" . }}-prometheus +{{- if .Values.prometheus.service.annotations }} + annotations: +{{ toYaml .Values.prometheus.service.annotations | indent 4 }} +{{- end }} +spec: +{{- if .Values.prometheus.service.clusterIP }} + clusterIP: {{ .Values.prometheus.service.clusterIP }} +{{- end }} +{{- if .Values.prometheus.service.externalIPs }} + externalIPs: +{{ toYaml .Values.prometheus.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.prometheus.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.prometheus.service.loadBalancerIP }} +{{- end }} +{{- if .Values.prometheus.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.prometheus.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - name: web + {{- if eq .Values.prometheus.service.type "NodePort" }} + nodePort: {{ .Values.global.nodePortPrefix }}{{ .Values.prometheus.service.nodePort }} + {{- end }} + port: 9090 + targetPort: web + selector: + app: prometheus + prometheus: {{ template "prometheus.fullname" . }}-prometheus + type: "{{ .Values.prometheus.service.type }}" diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/serviceaccount.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/serviceaccount.yaml new file mode 100644 index 00000000..82437523 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if .Values.prometheus.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "prometheus.serviceAccountName" . }} + labels: + app: {{ template "prometheus.name" . }}-prometheus +{{ include "prometheus.labels" . | indent 4 }} +imagePullSecrets: +{{ toYaml .Values.global.imagePullSecrets | indent 2 }} +{{- end }} diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/servicemonitor.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/servicemonitor.yaml new file mode 100644 index 00000000..ea2b81b6 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/templates/servicemonitor.yaml @@ -0,0 +1,30 @@ +{{- if .Values.prometheus.additionalServiceMonitors }} +apiVersion: v1 +kind: List +items: +{{- range .Values.prometheus.additionalServiceMonitors }} + - apiVersion: "monitoring.coreos.com/v1" + kind: ServiceMonitor + metadata: + name: {{ .name }} + "helm.sh/hook": post-install + "helm.sh/hook-weight": "1" + labels: + app: {{ template "prometheus.name" $ }}-prometheus +{{ include "prometheus.labels" $ | indent 8 }} + {{- if .additionalLabels }} +{{ toYaml .additionalLabels | indent 8 }} + {{- end }} + spec: + endpoints: +{{ toYaml .endpoints | indent 8 }} + {{- if .jobLabel }} + jobLabel: {{ .jobLabel }} + {{- end }} + namespaceSelector: + matchNames: + - {{ $.Release.Namespace | quote }} + selector: +{{ toYaml .selector | indent 8 }} release: {{ $.Release.Name | quote }} +{{- end }} +{{- end }} diff --git a/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/values.yaml b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/values.yaml new file mode 100644 index 00000000..e35c6735 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/helm/prometheus/values.yaml @@ -0,0 +1,69 @@ +## Deploy a Prometheus instance +## +prometheus: + serviceAccount: + create: true + name: "" + additionalServiceMonitors: + - name: service-monitor-collectd + additionalLabels: + collector: collectd + jobLabel: collectd + selector: + matchLabels: + app: collectd + endpoints: + - port: collectd-prometheus + interval: 10s + path: /metrics + - name: service-monitor-node-exporter + additionalLabels: + collector: prometheus-node-exporter + jobLabel: node-exporter + selector: + matchLabels: + app: prometheus-node-exporter + endpoints: + - port: metrics + interval: 30s + - name: service-monitor-cadvisor + additionalLabels: + collector: cadvisor + jobLabel: cadvisor + selector: + matchLabels: + app: cadvisor + endpoints: + - port: cadvisor-prometheus + interval: 10s + path: /metrics + + resources: {} + service: + type: ClusterIP + annotations: {} + labels: {} + clusterIP: "" + + ## To be used with a proxy extraContainer port + targetPort: 9090 + + ## List of IP addresses at which the Prometheus server service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + ## Port to expose on each node + ## Only used if service.type is 'NodePort' + ## + # nodePort: 90 + + ## Loadbalancer IP + ## Only use if service.type is "loadbalancer" + loadBalancerIP: "" + loadBalancerSourceRanges: [] + ## Service type + ## + #type: NodePort + + sessionAffinity: "" diff --git a/kud/tests/vnfs/comp-app/collection/app2/profile/manifest.yaml b/kud/tests/vnfs/comp-app/collection/app2/profile/manifest.yaml new file mode 100644 index 00000000..4d381d02 --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/profile/manifest.yaml @@ -0,0 +1,4 @@ +--- +version: v1 +type: + values: "override_values.yaml" diff --git a/kud/tests/vnfs/comp-app/collection/app2/profile/override_values.yaml b/kud/tests/vnfs/comp-app/collection/app2/profile/override_values.yaml new file mode 100644 index 00000000..6743ac5b --- /dev/null +++ b/kud/tests/vnfs/comp-app/collection/app2/profile/override_values.yaml @@ -0,0 +1,6 @@ +service: + type: ClusterIP + name: Prometheus + annotations: {} + labels: {} + clusterIP: ""
\ No newline at end of file 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") - } - }) -} |