github.com/oam-dev/kubevela@v1.9.11/references/cli/traits_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 cli 18 19 import ( 20 "bytes" 21 "context" 22 "os" 23 "strings" 24 25 . "github.com/onsi/ginkgo/v2" 26 . "github.com/onsi/gomega" 27 "sigs.k8s.io/yaml" 28 29 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" 30 util2 "github.com/oam-dev/kubevela/pkg/oam/util" 31 common2 "github.com/oam-dev/kubevela/pkg/utils/common" 32 "github.com/oam-dev/kubevela/pkg/utils/util" 33 ) 34 35 var _ = Describe("Test trait cli", func() { 36 37 When("there are container-image and configmap traits", func() { 38 BeforeEach(func() { 39 // Install trait locally 40 containerImage := v1beta1.TraitDefinition{} 41 Expect(yaml.Unmarshal([]byte(containerImageYaml), &containerImage)).Should(BeNil()) 42 Expect(k8sClient.Create(context.Background(), &containerImage)).Should(SatisfyAny(BeNil(), util2.AlreadyExistMatcher{})) 43 44 configMap := v1beta1.TraitDefinition{} 45 Expect(yaml.Unmarshal([]byte(configmapYaml), &configMap)).Should(BeNil()) 46 Expect(k8sClient.Create(context.Background(), &configMap)).Should(SatisfyAny(BeNil(), util2.AlreadyExistMatcher{})) 47 }) 48 49 It("should not have any err", func() { 50 arg := common2.Args{} 51 arg.SetClient(k8sClient) 52 buffer := bytes.NewBuffer(nil) 53 ioStreams := util.IOStreams{In: os.Stdin, Out: buffer, ErrOut: buffer} 54 cmd := NewTraitCommand(arg, "", ioStreams) 55 Expect(cmd.Execute()).Should(BeNil()) 56 buf, ok := ioStreams.Out.(*bytes.Buffer) 57 Expect(ok).Should(BeTrue()) 58 Expect(strings.Contains(buf.String(), "error")).Should(BeFalse()) 59 }) 60 }) 61 }) 62 63 const ( 64 containerImageYaml = `apiVersion: core.oam.dev/v1beta1 65 kind: TraitDefinition 66 metadata: 67 annotations: 68 definition.oam.dev/description: Set the image of the container. 69 name: container-image 70 namespace: vela-system 71 spec: 72 appliesToWorkloads: 73 - '*' 74 podDisruptive: true 75 schematic: 76 cue: 77 template: | 78 #PatchParams: { 79 // +usage=Specify the name of the target container, if not set, use the component name 80 containerName: *"" | string 81 // +usage=Specify the image of the container 82 image: string 83 // +usage=Specify the image pull policy of the container 84 imagePullPolicy: *"" | "IfNotPresent" | "Always" | "Never" 85 } 86 PatchContainer: { 87 _params: #PatchParams 88 name: _params.containerName 89 _baseContainers: context.output.spec.template.spec.containers 90 _matchContainers_: [ for _container_ in _baseContainers if _container_.name == name {_container_}] 91 _baseContainer: *_|_ | {...} 92 if len(_matchContainers_) == 0 { 93 err: "container \(name) not found" 94 } 95 if len(_matchContainers_) > 0 { 96 // +patchStrategy=retainKeys 97 image: _params.image 98 99 if _params.imagePullPolicy != "" { 100 // +patchStrategy=retainKeys 101 imagePullPolicy: _params.imagePullPolicy 102 } 103 } 104 } 105 patch: spec: template: spec: { 106 if parameter.containers == _|_ { 107 // +patchKey=name 108 containers: [{ 109 PatchContainer & {_params: { 110 if parameter.containerName == "" { 111 containerName: context.name 112 } 113 if parameter.containerName != "" { 114 containerName: parameter.containerName 115 } 116 image: parameter.image 117 imagePullPolicy: parameter.imagePullPolicy 118 }} 119 }] 120 } 121 if parameter.containers != _|_ { 122 // +patchKey=name 123 containers: [ for c in parameter.containers { 124 if c.containerName == "" { 125 err: "containerName must be set for containers" 126 } 127 if c.containerName != "" { 128 PatchContainer & {_params: c} 129 } 130 }] 131 } 132 } 133 parameter: *#PatchParams | close({ 134 // +usage=Specify the container image for multiple containers 135 containers: [...#PatchParams] 136 }) 137 errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}] 138 ` 139 configmapYaml = `apiVersion: core.oam.dev/v1beta1 140 kind: TraitDefinition 141 metadata: 142 annotations: 143 definition.oam.dev/description: Create/Attach configmaps on K8s pod for your workload which follows the pod spec in path 'spec.template'. This definition is DEPRECATED, please specify configmap in 'storage' instead. 144 labels: 145 custom.definition.oam.dev/deprecated: "true" 146 name: configmap 147 namespace: vela-system 148 spec: 149 appliesToWorkloads: 150 - '*' 151 podDisruptive: true 152 schematic: 153 cue: 154 template: | 155 patch: spec: template: spec: { 156 containers: [{ 157 // +patchKey=name 158 volumeMounts: [ 159 for v in parameter.volumes { 160 { 161 name: "volume-\(v.name)" 162 mountPath: v.mountPath 163 readOnly: v.readOnly 164 } 165 }, 166 ] 167 }, ...] 168 // +patchKey=name 169 volumes: [ 170 for v in parameter.volumes { 171 { 172 name: "volume-\(v.name)" 173 configMap: name: v.name 174 } 175 }, 176 ] 177 } 178 outputs: { 179 for v in parameter.volumes { 180 if v.data != _|_ { 181 "\(v.name)": { 182 apiVersion: "v1" 183 kind: "ConfigMap" 184 metadata: name: v.name 185 data: v.data 186 } 187 } 188 } 189 } 190 parameter: { 191 // +usage=Specify mounted configmap names and their mount paths in the container 192 volumes: [...{ 193 name: string 194 mountPath: string 195 readOnly: *false | bool 196 data?: [string]: string 197 }] 198 } 199 ` 200 )