github.com/oam-dev/kubevela@v1.9.11/pkg/velaql/view_test.go (about)

     1  /*
     2   Copyright 2021. The KubeVela Authors.
     3  
     4   Licensed under the Apache License, Version 2.0 (the "License");
     5   you may not use this file except in compliance with the License.
     6   You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10   Unless required by applicable law or agreed to in writing, software
    11   distributed under the License is distributed on an "AS IS" BASIS,
    12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   See the License for the specific language governing permissions and
    14   limitations under the License.
    15  */
    16  
    17  package velaql
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"os"
    23  	"strconv"
    24  	"testing"
    25  	"time"
    26  
    27  	. "github.com/onsi/ginkgo/v2"
    28  	. "github.com/onsi/gomega"
    29  	"github.com/stretchr/testify/assert"
    30  	corev1 "k8s.io/api/core/v1"
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	pkgtypes "k8s.io/apimachinery/pkg/types"
    33  	"sigs.k8s.io/controller-runtime/pkg/client"
    34  
    35  	"github.com/oam-dev/kubevela/apis/types"
    36  )
    37  
    38  var _ = Describe("Test VelaQL View", func() {
    39  	var ctx = context.Background()
    40  
    41  	It("Test query a sample view", func() {
    42  		parameter := map[string]string{
    43  			"apiVersion": "v1",
    44  			"kind":       "Pod",
    45  			"name":       pod.Name,
    46  		}
    47  
    48  		velaQL := fmt.Sprintf("%s{%s}.%s", readView.Name, Map2URLParameter(parameter), "objStatus")
    49  		query, err := ParseVelaQL(velaQL)
    50  		Expect(err).ShouldNot(HaveOccurred())
    51  
    52  		queryValue, err := viewHandler.QueryView(context.Background(), query)
    53  		Expect(err).Should(BeNil())
    54  
    55  		podStatus := corev1.PodStatus{}
    56  		Expect(queryValue.UnmarshalTo(&podStatus)).Should(BeNil())
    57  	})
    58  
    59  	It("Test query view with wrong request", func() {
    60  		parameter := map[string]string{
    61  			"apiVersion": "v1",
    62  			"kind":       "Pod",
    63  			"name":       pod.Name,
    64  		}
    65  
    66  		By("query view with an non-existent result")
    67  		velaQL := fmt.Sprintf("%s{%s}.%s", readView.Name, Map2URLParameter(parameter), "appStatus")
    68  		query, err := ParseVelaQL(velaQL)
    69  		Expect(err).ShouldNot(HaveOccurred())
    70  		v, err := viewHandler.QueryView(context.Background(), query)
    71  		Expect(err).ShouldNot(HaveOccurred())
    72  		s, err := v.String()
    73  		Expect(err).ShouldNot(HaveOccurred())
    74  		Expect(s).Should(Equal("null\n"))
    75  
    76  		By("query an non-existent view")
    77  		velaQL = fmt.Sprintf("%s{%s}.%s", "view-resource", Map2URLParameter(parameter), "objStatus")
    78  		query, err = ParseVelaQL(velaQL)
    79  		Expect(err).ShouldNot(HaveOccurred())
    80  		_, err = viewHandler.QueryView(context.Background(), query)
    81  		Expect(err).Should(HaveOccurred())
    82  	})
    83  
    84  	It("Test apply resource in view", func() {
    85  		parameter := map[string]string{
    86  			"apiVersion": "v1",
    87  			"kind":       "Namespace",
    88  			"name":       "test-namespace",
    89  		}
    90  		velaQL := fmt.Sprintf("%s{%s}.%s", applyView.Name, Map2URLParameter(parameter), "objStatus")
    91  		query, err := ParseVelaQL(velaQL)
    92  		Expect(err).ShouldNot(HaveOccurred())
    93  		_, err = viewHandler.QueryView(context.Background(), query)
    94  		Expect(err).ShouldNot(HaveOccurred())
    95  
    96  		ns := corev1.Namespace{}
    97  		Expect(k8sClient.Get(ctx, client.ObjectKey{Name: "test-namespace"}, &ns)).Should(BeNil())
    98  	})
    99  })
   100  
   101  func Map2URLParameter(parameter map[string]string) string {
   102  	var res string
   103  	for k, v := range parameter {
   104  		res += fmt.Sprintf("%s=\"%s\",", k, v)
   105  	}
   106  	return res
   107  }
   108  
   109  func TestParseViewIntoConfigMap(t *testing.T) {
   110  	cases := []struct {
   111  		cueStr  string
   112  		succeed bool
   113  	}{
   114  		{
   115  			cueStr:  `{`,
   116  			succeed: false,
   117  		},
   118  		{
   119  			cueStr:  `{}`,
   120  			succeed: false,
   121  		},
   122  		{
   123  			cueStr: `{}
   124  status: something`,
   125  			succeed: false,
   126  		},
   127  		{
   128  			cueStr: `something: {}
   129  status: something`,
   130  			succeed: true,
   131  		},
   132  		{
   133  			cueStr: `something: {}
   134  export: something`,
   135  			succeed: true,
   136  		},
   137  	}
   138  	for _, c := range cases {
   139  		cm, err := ParseViewIntoConfigMap(c.cueStr, "name")
   140  		assert.Equal(t, c.succeed, err == nil, err)
   141  		if err == nil {
   142  			assert.Equal(t, c.cueStr, cm.Data["template"])
   143  		}
   144  	}
   145  }
   146  
   147  func getViewConfigMap(name string) (*corev1.ConfigMap, error) {
   148  	cm := &corev1.ConfigMap{
   149  		TypeMeta: metav1.TypeMeta{
   150  			APIVersion: "v1",
   151  			Kind:       "ConfigMap",
   152  		},
   153  		ObjectMeta: metav1.ObjectMeta{
   154  			Name:      name,
   155  			Namespace: types.DefaultKubeVelaNS,
   156  		},
   157  	}
   158  
   159  	err := k8sClient.Get(context.TODO(), pkgtypes.NamespacedName{
   160  		Namespace: cm.GetNamespace(),
   161  		Name:      cm.GetName(),
   162  	}, cm)
   163  
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  
   168  	return cm, nil
   169  }
   170  
   171  var _ = Describe("test StoreViewFromFile", func() {
   172  	Describe("normal creation", func() {
   173  		It("from local file", func() {
   174  			cueStr := "something: {}\nstatus: something"
   175  			filename := "norm-create.cue"
   176  			err := os.WriteFile(filename, []byte(cueStr), 0600)
   177  			Expect(err).Should(Succeed())
   178  			defer os.RemoveAll(filename)
   179  			viewName := "test-view-" + strconv.FormatInt(time.Now().UnixNano(), 10)
   180  			err = StoreViewFromFile(context.TODO(), k8sClient, filename, viewName)
   181  			Expect(err).Should(Succeed())
   182  			// We should be able to get it.
   183  			_, err = getViewConfigMap(viewName)
   184  			Expect(err).Should(Succeed())
   185  		})
   186  
   187  		It("update a previously updated view", func() {
   188  			cueStr := "something: {}\nstatus: something"
   189  			filename := "norm-create.cue"
   190  			err := os.WriteFile(filename, []byte(cueStr), 0600)
   191  			Expect(err).Should(Succeed())
   192  			defer os.RemoveAll(filename)
   193  			viewName := "test-view-" + strconv.FormatInt(time.Now().UnixNano(), 10)
   194  			err = StoreViewFromFile(context.TODO(), k8sClient, filename, viewName)
   195  			Expect(err).Should(Succeed())
   196  			// Update it
   197  			newCueStr := "something: {a: \"123\"}\nstatus: something"
   198  			err = os.WriteFile(filename, []byte(newCueStr), 0600)
   199  			Expect(err).Should(Succeed())
   200  			err = StoreViewFromFile(context.TODO(), k8sClient, filename, viewName)
   201  			Expect(err).Should(Succeed())
   202  			// It should be updates
   203  			cm, err := getViewConfigMap(viewName)
   204  			Expect(err).Should(Succeed())
   205  			Expect(cm.Data["template"]).Should(Equal(newCueStr))
   206  		})
   207  	})
   208  
   209  	Describe("failed creation", func() {
   210  		It("from local file", func() {
   211  			filename := "failed-create-non-existent.cue"
   212  			err := StoreViewFromFile(context.TODO(), k8sClient, filename, "1234")
   213  			Expect(err).ShouldNot(Succeed())
   214  		})
   215  
   216  		It("invalid cue", func() {
   217  			cueStr := "status: what-is-this"
   218  			filename := "failed-create-invalid.cue"
   219  			err := os.WriteFile(filename, []byte(cueStr), 0600)
   220  			Expect(err).Should(Succeed())
   221  			defer os.RemoveAll(filename)
   222  			err = StoreViewFromFile(context.TODO(), k8sClient, filename, "5678")
   223  			Expect(err).ShouldNot(Succeed())
   224  		})
   225  	})
   226  })