2 ==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================================
24 "github.com/spf13/viper"
30 "github.com/stretchr/testify/assert"
31 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/cm"
32 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/appmgr"
33 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/models"
34 "gerrit.o-ran-sc.org/r/ric-plt/appmgr/pkg/util"
37 var caughtKubeExecArgs string
38 var kubeExecRetOut string
39 var kubeExecRetErr error
40 var caughtHelmExecArgs string
41 var helmExecRetOut string
42 var helmExecRetErr error
43 var helmStatusOutput = `
44 LAST DEPLOYED: Sat Mar 9 06:50:45 2019
50 NAME READY STATUS RESTARTS AGE
51 dummy-xapp-8984fc9fd-bkcbp 1/1 Running 0 55m
52 dummy-xapp-8984fc9fd-l6xch 1/1 Running 0 55m
53 dummy-xapp-8984fc9fd-pp4hg 1/1 Running 0 55m
56 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
57 dummy-xapp-dummy-xapp-chart ClusterIP 10.102.184.212 <none> 80/TCP 55m
59 ==> v1beta1/Deployment
60 NAME READY UP-TO-DATE AVAILABLE AGE
61 dummy-xapp 3/3 3 3 55m
64 var helListAllOutput = `Next: ""
67 Chart: dummy-xapp-chart-0.1.0
72 Updated: Mon Mar 11 06:55:05 2019
74 Chart: dummy-xapp-chart-0.1.0
79 Updated: Mon Mar 11 06:55:05 2019
86 Updated: Sun Mar 24 07:17:00 2019
89 var helListOutput = `Next: ""
92 Chart: dummy-xapp-chart-0.1.0
97 Updated: Mon Mar 11 06:55:05 2019
100 var kubeServiceOutput = `{
104 "creationTimestamp": "2020-03-31T12:27:12Z",
106 "app": "ricxapp-dummy-xapp",
107 "chart": "dummy-xapp-0.0.4",
108 "heritage": "Tiller",
109 "release": "dummy-xapp"
111 "name": "service-ricxapp-dummy-xapp-rmr",
112 "namespace": "ricxapp",
113 "resourceVersion": "4423380",
114 "selfLink": "/api/v1/namespaces/ricxapp/services/service-ricxapp-dummy-xapp-rmr",
115 "uid": "2254b77d-7dd6-43e0-beff-3e2a7b24c89a"
118 "clusterIP": "10.98.239.107",
124 "targetPort": "rmrdata"
130 "targetPort": "rmrroute"
134 "app": "ricxapp-dummy-xapp",
135 "release": "dummy-xapp"
137 "sessionAffinity": "None",
147 func TestMain(m *testing.M) {
149 appmgr.Logger.SetLevel(0)
155 func TestInit(t *testing.T) {
156 defer func() { resetHelmExecMock() }()
157 var expectedHelmCommand string = ""
158 helmExec = mockedHelmExec
161 if cm.EnvHelmVersion == cm.HELM_VERSION_2{
162 expectedHelmCommand = "init -c --skip-refresh"
163 if caughtHelmExecArgs != expectedHelmCommand {
164 t.Errorf("Init failed: expected %v, got %v", expectedHelmCommand, caughtHelmExecArgs)
169 func TestAddRepoSuccess(t *testing.T) {
172 removeTestUsernameFile()
173 removeTestPasswordFile()
175 helmExec = mockedHelmExec
177 if err := writeTestUsernameFile(); err != nil {
178 t.Errorf("AddRepo username file create failed: %s", err)
181 if err := writeTestPasswordFile(); err != nil {
182 t.Errorf("AddRepo password file create failed: %s", err)
186 if _, err := NewHelm().AddRepo(); err != nil {
187 t.Errorf("AddRepo failed: %v", err)
190 if !strings.Contains(caughtHelmExecArgs, "repo add") {
191 t.Errorf("AddRepo failed: expected %v, got %v", "repo add", caughtHelmExecArgs)
193 NewHelm().initDone = true
194 NewHelm().Initialize()
197 func TestFuncsWithHelmv3(t *testing.T){
201 if err = os.Setenv("HELMVERSION", "3"); err != nil {
202 t.Logf("Tiller Env Setting Failed: %v", err.Error())
206 xapp, err := helm.Status(name)
208 t.Logf("Status returned: %v", err)
210 xapp2, err := helm.Delete(name)
212 assert.NotEqual(t, err, "Error: release: not found")
214 t.Logf("xapp : %+v, Xapp2 : %+v",xapp,xapp2)
218 if version := helm.GetVersion(name); version != "" {
219 t.Logf("GetVersion expected to return empty string, got %v", version)
222 x := models.XappDescriptor{XappName: &name, Namespace: "ricxapp"}
223 x.OverrideFile = "../../test/dummy-xapp_values.json"
224 if args := helm.GetInstallArgs(x, false); args == "" {
225 t.Logf("GetInstallArgs failed: got %v", args)
228 if err = os.Setenv("HELMVERSION", "2"); err != nil {
229 t.Logf("after set Tiller Env Setting Failed: %v", err.Error())
234 func TestAddRepoReturnsErrorIfNoUsernameFile(t *testing.T) {
235 if _, err := NewHelm().AddRepo(); err == nil {
236 t.Errorf("AddRepo expected to fail but it didn't")
240 func TestAddRepoReturnsErrorIfNoPasswordFile(t *testing.T) {
241 defer func() { resetHelmExecMock(); removeTestUsernameFile() }()
242 helmExec = mockedHelmExec
244 if err := writeTestUsernameFile(); err != nil {
245 t.Errorf("AddRepo username file create failed: %s", err)
248 if _, err := NewHelm().AddRepo(); err == nil {
249 t.Errorf("AddRepo expected to fail but it didn't")
253 func TestInstallSuccess(t *testing.T) {
255 xappDesc := models.XappDescriptor{XappName: &name, Namespace: "ricxapp"}
257 defer func() { resetHelmExecMock() }()
258 helmExec = mockedHelmExec
259 helmExecRetOut = helmStatusOutput
261 defer func() { resetKubeExecMock() }()
262 kubeExec = mockedKubeExec
263 kubeExecRetOut = kubeServiceOutput
265 xapp, err := NewHelm().Install(xappDesc)
267 t.Errorf("Install failed: %v", err)
269 validateXappModel(t, xapp)
272 func TestInstallReturnsErrorIfHelmRepoUpdateFails(t *testing.T) {
274 xappDesc := models.XappDescriptor{XappName: &name, Namespace: "ricxapp"}
276 defer func() { resetHelmExecMock() }()
277 helmExec = mockedHelmExec
278 helmExecRetErr = errors.New("some helm command error")
280 if _, err := NewHelm().Install(xappDesc); err == nil {
281 t.Errorf("Install expected to fail but it didn't")
285 func TestStatusSuccess(t *testing.T) {
288 defer func() { resetHelmExecMock() }()
289 helmExec = mockedHelmExec
290 helmExecRetOut = helmStatusOutput
292 xapp, err := NewHelm().Status(name)
294 t.Errorf("Status failed: %v", err)
296 validateXappModel(t, xapp)
299 func TestStatusReturnsErrorIfHelmStatusFails(t *testing.T) {
302 defer func() { resetHelmExecMock() }()
303 helmExec = mockedHelmExec
304 helmExecRetErr = errors.New("some helm command error")
306 if _, err := NewHelm().Status(name); err == nil {
307 t.Errorf("Status expected to fail but it didn't")
309 assert.Equal(t, err, helmExecRetErr)
313 func TestParseStatusSuccess(t *testing.T) {
314 defer func() { resetHelmExecMock() }()
315 var expectedHelmCommand string = ""
316 helmExec = mockedHelmExec
317 helmExecRetOut = helListOutput
319 defer func() { resetKubeExecMock() }()
320 kubeExec = mockedKubeExec
321 kubeExecRetOut = kubeServiceOutput
323 xapp, err := NewHelm().ParseStatus("dummy-xapp", helmStatusOutput)
325 t.Errorf("ParseStatus failed: %v", err)
328 validateXappModel(t, xapp)
330 if cm.EnvHelmVersion == cm.HELM_VERSION_2 {
331 expectedHelmCommand = "list --deployed --output yaml --namespace=ricxapp dummy-xapp"
333 expectedHelmCommand = "list --deployed --output yaml --namespace=ricxapp -f dummy-xapp"
335 if caughtHelmExecArgs != expectedHelmCommand {
336 t.Errorf("ParseStatus failed: expected %v, got %v", expectedHelmCommand, caughtHelmExecArgs)
340 func TestListSuccess(t *testing.T) {
341 defer func() { resetHelmExecMock() }()
342 helmExec = mockedHelmExec
343 helmExecRetOut = helListAllOutput
345 names, err := NewHelm().List()
347 t.Errorf("List failed: %v", err)
350 if !reflect.DeepEqual(names, []string{"dummy-xapp", "dummy-xapp2"}) {
351 t.Errorf("List failed: %v", err)
353 expectedHelmCommand := "list --all --deployed --output yaml --namespace=ricxapp"
354 if caughtHelmExecArgs != expectedHelmCommand {
355 t.Errorf("List: expected %v, got %v", expectedHelmCommand, caughtHelmExecArgs)
358 var str models.AllDeployableXapps
359 str = NewHelm().SearchAll()
361 t.Logf("Search end..str : %s\n",str)
367 func TestListReturnsErrorIfHelmListFails(t *testing.T) {
368 defer func() { resetHelmExecMock() }()
369 helmExec = mockedHelmExec
370 helmExecRetErr = errors.New("some helm command error")
372 if _, err := NewHelm().List(); err == nil {
373 t.Errorf("List expected to fail but it didn't")
378 func TestDeleteSuccess(t *testing.T) {
381 var expectedHelmCommand string = ""
382 defer func() { resetHelmExecMock() }()
383 helmExec = mockedHelmExec
384 helmExecRetOut = helmStatusOutput
386 defer func() { resetKubeExecMock() }()
387 kubeExec = mockedKubeExec
388 kubeExecRetOut = kubeServiceOutput
390 xapp, err := NewHelm().Delete(name)
392 t.Errorf("Delete failed: %v", err)
395 validateXappModel(t, xapp)
397 if cm.EnvHelmVersion == cm.HELM_VERSION_2 {
398 expectedHelmCommand = "del --purge dummy-xapp"
400 expectedHelmCommand = "uninstall dummy-xapp -n ricxapp"
402 if caughtHelmExecArgs != expectedHelmCommand {
403 t.Errorf("Delete failed: expected %v, got %v", expectedHelmCommand, caughtHelmExecArgs)
407 func TestDeleteReturnsErrorIfHelmStatusFails(t *testing.T) {
410 defer func() { resetHelmExecMock() }()
411 helmExec = mockedHelmExec
412 helmExecRetErr = errors.New("some helm command error")
414 if _, err := NewHelm().Delete(name); err == nil {
415 t.Errorf("Delete expected to fail but it didn't")
419 func TestFetchSuccessIfCmdArgHasTestSuffix(t *testing.T) {
420 if err := NewHelm().Fetch("lsfuis", "../../helm_chart/appmgr/values.yaml"); err != nil {
421 t.Errorf("Fetch failed: %v", err)
425 func TestGetVersionSuccess(t *testing.T) {
426 defer func() { resetHelmExecMock() }()
427 var expectedHelmCommand string = ""
428 helmExec = mockedHelmExec
429 helmExecRetOut = helListOutput
431 if version := NewHelm().GetVersion("dummy-xapp"); version != "1.0" {
432 t.Errorf("GetVersion failed: expected 1.0, got %v", version)
435 if cm.EnvHelmVersion == cm.HELM_VERSION_2{
436 expectedHelmCommand = "list --deployed --output yaml --namespace=ricxapp dummy-xapp"
438 expectedHelmCommand = "list --deployed --output yaml --namespace=ricxapp -f dummy-xapp"
440 if caughtHelmExecArgs != expectedHelmCommand {
441 t.Errorf("GetVersion failed: expected %v, got %v", expectedHelmCommand, caughtHelmExecArgs)
445 func TestGetVersionReturnsEmptyStringIfHelmListFails(t *testing.T) {
446 defer func() { resetHelmExecMock() }()
447 helmExec = mockedHelmExec
448 helmExecRetErr = errors.New("some helm command error")
450 if version := NewHelm().GetVersion("dummy-xapp"); version != "" {
451 t.Errorf("GetVersion expected to return empty string, got %v", version)
455 func TestGetAddressSuccess(t *testing.T) {
456 ip, port := NewHelm().GetAddress(helmStatusOutput)
457 if ip != "10.102.184.212" {
458 t.Errorf("GetAddress failed: expected 10.102.184.212, got %v", ip)
460 if port != "80/TCP" {
461 t.Errorf("GetAddress failed: expected 80/TCP, got %v", port)
465 func TestGetEndpointInfoSuccess(t *testing.T) {
466 defer func() { resetKubeExecMock() }()
467 kubeExec = mockedKubeExec
468 kubeExecRetOut = kubeServiceOutput
470 svc, port := NewHelm().GetEndpointInfo("dummy-xapp")
472 expectedSvc := "service-ricxapp-dummy-xapp-rmr.ricxapp"
473 if svc != expectedSvc {
474 t.Errorf("GetEndpointInfo failed: expected %v, got %v", expectedSvc, svc)
477 t.Errorf("GetEndpointInfo failed: expected port 4560, got %v", port)
479 expectedKubeCommand := " get service -n ricxapp service-ricxapp-dummy-xapp-rmr -o json"
480 if caughtKubeExecArgs != expectedKubeCommand {
481 t.Errorf("GetEndpointInfo failed: expected %v, got %v", expectedKubeCommand, caughtKubeExecArgs)
485 func TestGetEndpointInfoReturnsDefaultPortIfJsonParseFails(t *testing.T) {
486 defer func() { resetKubeExecMock() }()
487 kubeExec = mockedKubeExec
488 kubeExecRetOut = "not-json-syntax"
490 svc, port := NewHelm().GetEndpointInfo("dummy-xapp")
491 expectedSvc := "service-ricxapp-dummy-xapp-rmr.ricxapp"
492 if svc != expectedSvc {
493 t.Errorf("GetEndpointInfo failed: expected %v, got %v", expectedSvc, svc)
496 t.Errorf("GetEndpointInfo failed: expected port 4560, got %v", port)
500 func TestGetEndpointInfoReturnsDefaultPortIfKubeGetServiceFails(t *testing.T) {
501 defer func() { resetKubeExecMock() }()
502 kubeExec = mockedKubeExec
503 kubeExecRetErr = errors.New("some helm command error")
505 svc, port := NewHelm().GetEndpointInfo("dummy-xapp")
506 expectedSvc := "service-ricxapp-dummy-xapp-rmr.ricxapp"
507 if svc != expectedSvc {
508 t.Errorf("GetEndpointInfo failed: expected %v, got %v", expectedSvc, svc)
511 t.Errorf("GetEndpointInfo failed: expected port 4560, got %v", port)
515 func TestHelmStatusAllSuccess(t *testing.T) {
516 defer func() { resetHelmExecMock() }()
517 helmExec = mockedHelmExec
518 helmExecRetOut = helListAllOutput
520 if _, err := NewHelm().StatusAll(); err != nil {
521 t.Errorf("StatusAll failed: %v", err)
523 // Todo: check StatusAll response content
526 func TestStatusAllReturnsErrorIfHelmListFails(t *testing.T) {
527 defer func() { resetHelmExecMock() }()
528 helmExec = mockedHelmExec
529 helmExecRetErr = errors.New("some helm command error")
531 if _, err := NewHelm().StatusAll(); err == nil {
532 t.Errorf("StatusAll expected to fail but it didn't")
536 func TestGetNamesSuccess(t *testing.T) {
537 names, err := NewHelm().GetNames(helListAllOutput)
539 t.Errorf("GetNames failed: %v", err)
541 if !reflect.DeepEqual(names, []string{"dummy-xapp", "dummy-xapp2"}) {
542 t.Errorf("GetNames failed: %v", err)
546 func TestGetNamesFail(t *testing.T) {
547 names, err := NewHelm().GetNames("helListAll")
549 t.Errorf("GetNames failed: %v", err)
551 if reflect.DeepEqual(names, []string{"dummy-xapp", "dummy-xapp2"}) {
552 t.Errorf("GetNames succ")
555 func TestAddTillerEnv(t *testing.T) {
556 if err := NewHelm().AddTillerEnv(); err != nil {
557 t.Errorf("AddTillerEnv failed!")
561 func TestGetInstallArgs(t *testing.T) {
563 var expectedArgs string = ""
565 x := models.XappDescriptor{XappName: &name, Namespace: "ricxapp"}
567 if cm.EnvHelmVersion == cm.HELM_VERSION_3 {
568 expectedArgs = "install dummy-xapp helm-repo/dummy-xapp --namespace=ricxapp"
570 expectedArgs = "install helm-repo/dummy-xapp --namespace=ricxapp --name=dummy-xapp"
573 if args := NewHelm().GetInstallArgs(x, false); args != expectedArgs {
574 t.Errorf("GetInstallArgs failed: expected '%v', got '%v'", expectedArgs, args)
577 expectedArgs += " --set ricapp.appconfig.override=dummy-xapp-appconfig"
578 if args := NewHelm().GetInstallArgs(x, true); args != expectedArgs {
579 t.Errorf("GetInstallArgs failed: expected %v, got %v", expectedArgs, args)
582 x.HelmVersion = "1.2.3"
583 if cm.EnvHelmVersion == cm.HELM_VERSION_3 {
584 expectedArgs = "install dummy-xapp helm-repo/dummy-xapp --namespace=ricxapp --version=1.2.3"
586 expectedArgs = "install helm-repo/dummy-xapp --namespace=ricxapp --version=1.2.3 --name=dummy-xapp"
588 if args := NewHelm().GetInstallArgs(x, false); args != expectedArgs {
589 t.Errorf("GetInstallArgs failed: expected %v, got %v", expectedArgs, args)
593 x.ReleaseName = "ueec-xapp"
594 if cm.EnvHelmVersion == cm.HELM_VERSION_3 {
595 expectedArgs = "install dummy-xapp helm-repo/dummy-xapp --namespace=ricxapp --version=1.2.3"
597 expectedArgs = "install helm-repo/dummy-xapp --namespace=ricxapp --version=1.2.3 --name=ueec-xapp"
599 if args := NewHelm().GetInstallArgs(x, false); args != expectedArgs {
600 t.Errorf("GetInstallArgs failed: expected %v, got %v", expectedArgs, args)
603 x.OverrideFile = "../../test/dummy-xapp_values.json"
604 expectedArgs += " -f=/tmp/appmgr_override.yaml"
605 if args := NewHelm().GetInstallArgs(x, false); args != expectedArgs {
606 t.Errorf("GetInstallArgs failed: expected %v, got %v", expectedArgs, args)
610 func writeTestUsernameFile() error {
611 f, err := os.Create(viper.GetString("helm.helm-username-file"))
615 _, err = f.WriteString("some-username")
620 func removeTestUsernameFile() error {
621 return os.Remove(viper.GetString("helm.helm-username-file"))
624 func writeTestPasswordFile() (err error) {
625 f, err := os.Create(viper.GetString("helm.helm-password-file"))
630 _, err = f.WriteString("some-password")
635 func removeTestPasswordFile() error {
636 return os.Remove(viper.GetString("helm.helm-password-file"))
639 func getXappData() (x models.Xapp) {
640 //name1 := "dummy-xapp-8984fc9fd-l6xch"
641 //name2 := "dummy-xapp-8984fc9fd-pp4hg"
642 x = generateXapp("dummy-xapp", "deployed", "1.0", "dummy-xapp-8984fc9fd-bkcbp", "running", "service-ricxapp-dummy-xapp-rmr.ricxapp", "4560")
643 //x.Instances = append(x.Instances, x.Instances[0])
644 //x.Instances = append(x.Instances, x.Instances[0])
645 //x.Instances[1].Name = &name1
646 //x.Instances[2].Name = &name2
651 func generateXapp(name, status, ver, iname, istatus, ip, port string) (x models.Xapp) {
655 p, _ := strconv.Atoi(port)
656 var msgs appmgr.RtmData
658 instance := &models.XappInstance{
663 TxMessages: msgs.TxMessages,
664 RxMessages: msgs.RxMessages,
666 x.Instances = append(x.Instances, instance)
671 func mockedKubeExec(args string) (out []byte, err error) {
672 caughtKubeExecArgs = args
673 return []byte(kubeExecRetOut), kubeExecRetErr
676 func resetKubeExecMock() {
677 kubeExec = util.KubectlExec
678 caughtKubeExecArgs = ""
683 func mockedHelmExec(args string) (out []byte, err error) {
684 caughtHelmExecArgs = args
685 return []byte(helmExecRetOut), helmExecRetErr
688 func resetHelmExecMock() {
689 helmExec = util.HelmExec
690 caughtHelmExecArgs = ""
695 func validateXappModel(t *testing.T, xapp models.Xapp) {
696 expXapp := getXappData()
699 if *expXapp.Name != *xapp.Name || expXapp.Status != xapp.Status || expXapp.Version != xapp.Version {
700 t.Errorf("\n%v \n%v", *xapp.Name, *expXapp.Name)
703 if *expXapp.Instances[0].Name != *xapp.Instances[0].Name || expXapp.Instances[0].Status != xapp.Instances[0].Status {
704 t.Errorf("\n1:%v 2:%v", *expXapp.Instances[0].Name, *xapp.Instances[0].Name)
707 if expXapp.Instances[0].IP != xapp.Instances[0].IP || expXapp.Instances[0].Port != xapp.Instances[0].Port {
708 t.Errorf("\n%v - %v, %v - %v", expXapp.Instances[0].IP, xapp.Instances[0].IP, expXapp.Instances[0].Port, xapp.Instances[0].Port)