2021-04-11 14:10:16 +08:00
/ *
2021-04-11 21:00:14 +08:00
Copyright 2021 The KubeVela Authors .
2021-04-11 14:10:16 +08:00
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 appfile
import (
2021-07-22 18:53:30 +08:00
"context"
2021-04-30 16:28:00 +08:00
"encoding/json"
2021-04-11 14:10:16 +08:00
"fmt"
"testing"
2021-08-30 11:43:20 +08:00
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
2022-03-21 12:02:30 +08:00
appsv1 "k8s.io/api/apps/v1"
2021-08-30 11:43:20 +08:00
2022-02-08 16:26:16 +08:00
"cuelang.org/go/cue"
2021-04-11 14:10:16 +08:00
"github.com/crossplane/crossplane-runtime/pkg/test"
"github.com/google/go-cmp/cmp"
2021-04-30 16:28:00 +08:00
terraformtypes "github.com/oam-dev/terraform-controller/api/types/crossplane-runtime"
terraformapi "github.com/oam-dev/terraform-controller/api/v1beta1"
2021-04-11 14:10:16 +08:00
"github.com/pkg/errors"
2021-05-13 21:46:45 +08:00
"gotest.tools/assert"
2021-04-11 14:10:16 +08:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/pointer"
2021-08-15 10:53:05 +08:00
"sigs.k8s.io/yaml"
2021-04-11 14:10:16 +08:00
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
2021-07-22 18:53:30 +08:00
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
2021-04-11 14:10:16 +08:00
oamtypes "github.com/oam-dev/kubevela/apis/types"
2021-06-02 15:37:06 +08:00
"github.com/oam-dev/kubevela/pkg/cue/definition"
2021-08-30 11:43:20 +08:00
"github.com/oam-dev/kubevela/pkg/cue/model"
2022-02-28 10:30:55 +08:00
"github.com/oam-dev/kubevela/pkg/oam"
2021-04-11 14:10:16 +08:00
"github.com/oam-dev/kubevela/pkg/oam/util"
)
var _ = Describe ( "Test Helm schematic appfile" , func ( ) {
var (
2021-09-23 15:05:25 +08:00
appName = "test-app"
compName = "test-comp"
workloadName = "test-workload"
2021-04-11 14:10:16 +08:00
)
It ( "Test generate AppConfig resources from Helm schematic" , func ( ) {
appFile := & Appfile {
2021-09-12 10:12:46 +08:00
Name : appName ,
Namespace : "default" ,
AppRevisionName : appName + "-v1" ,
RelatedTraitDefinitions : map [ string ] * v1beta1 . TraitDefinition {
"scaler" : {
Spec : v1beta1 . TraitDefinitionSpec { } ,
} ,
} ,
2021-04-11 14:10:16 +08:00
Workloads : [ ] * Workload {
{
2021-09-23 15:05:25 +08:00
Name : workloadName ,
2021-04-11 14:10:16 +08:00
Type : "webapp-chart" ,
CapabilityCategory : oamtypes . HelmCategory ,
Params : map [ string ] interface { } {
"image" : map [ string ] interface { } {
"tag" : "5.1.2" ,
} ,
} ,
engine : definition . NewWorkloadAbstractEngine ( compName , pd ) ,
Traits : [ ] * Trait {
{
Name : "scaler" ,
Params : map [ string ] interface { } {
"replicas" : float64 ( 10 ) ,
} ,
engine : definition . NewTraitAbstractEngine ( "scaler" , pd ) ,
Template : `
outputs : scaler : {
apiVersion : "core.oam.dev/v1alpha2"
kind : "ManualScalerTrait"
spec : {
replicaCount : parameter . replicas
}
}
parameter : {
//+short=r
replicas : * 1 | int
}
` ,
} ,
} ,
FullTemplate : & Template {
2021-05-24 23:32:02 +08:00
Reference : common . WorkloadTypeDescriptor {
Definition : common . WorkloadGVK {
APIVersion : "apps/v1" ,
Kind : "Deployment" ,
} ,
2021-04-11 14:10:16 +08:00
} ,
Helm : & common . Helm {
2021-10-13 16:16:53 +08:00
Release : * util . Object2RawExtension ( map [ string ] interface { } {
2021-04-11 14:10:16 +08:00
"chart" : map [ string ] interface { } {
"spec" : map [ string ] interface { } {
"chart" : "podinfo" ,
"version" : "5.1.4" ,
} ,
} ,
} ) ,
2021-10-13 16:16:53 +08:00
Repository : * util . Object2RawExtension ( map [ string ] interface { } {
2021-12-16 15:17:00 +08:00
"url" : "https://charts.kubevela.net/example/" ,
2021-04-11 14:10:16 +08:00
} ) ,
} ,
} ,
} ,
} ,
}
By ( "Generate ApplicationConfiguration and Components" )
2021-06-24 15:06:58 +08:00
components , err := appFile . GenerateComponentManifests ( )
2021-04-11 14:10:16 +08:00
Expect ( err ) . To ( BeNil ( ) )
2021-06-24 15:06:58 +08:00
expectCompManifest := & oamtypes . ComponentManifest {
2021-09-23 15:05:25 +08:00
Name : workloadName ,
2021-06-24 15:06:58 +08:00
StandardWorkload : & unstructured . Unstructured {
Object : map [ string ] interface { } {
"apiVersion" : "apps/v1" ,
"kind" : "Deployment" ,
"metadata" : map [ string ] interface { } {
"labels" : map [ string ] interface { } {
"workload.oam.dev/type" : "webapp-chart" ,
"app.oam.dev/component" : compName ,
"app.oam.dev/name" : appName ,
"app.oam.dev/appRevision" : appName + "-v1" ,
} } } } ,
Traits : [ ] * unstructured . Unstructured {
{
Object : map [ string ] interface { } {
"apiVersion" : "core.oam.dev/v1alpha2" ,
"kind" : "ManualScalerTrait" ,
"metadata" : map [ string ] interface { } {
"labels" : map [ string ] interface { } {
"app.oam.dev/component" : compName ,
"app.oam.dev/name" : appName ,
"trait.oam.dev/type" : "scaler" ,
"trait.oam.dev/resource" : "scaler" ,
"app.oam.dev/appRevision" : appName + "-v1" ,
2021-04-11 14:10:16 +08:00
} ,
} ,
2021-06-24 15:06:58 +08:00
"spec" : map [ string ] interface { } { "replicaCount" : int64 ( 10 ) } ,
2021-04-11 14:10:16 +08:00
} ,
} ,
} ,
2021-06-24 15:06:58 +08:00
PackagedWorkloadResources : [ ] * unstructured . Unstructured {
{
Object : map [ string ] interface { } {
2021-04-11 14:10:16 +08:00
"apiVersion" : "helm.toolkit.fluxcd.io/v2beta1" ,
"kind" : "HelmRelease" ,
"metadata" : map [ string ] interface { } {
"name" : fmt . Sprintf ( "%s-%s" , appName , compName ) ,
"namespace" : "default" ,
} ,
"spec" : map [ string ] interface { } {
"chart" : map [ string ] interface { } {
"spec" : map [ string ] interface { } {
"sourceRef" : map [ string ] interface { } {
"kind" : "HelmRepository" ,
"name" : fmt . Sprintf ( "%s-%s" , appName , compName ) ,
"namespace" : "default" ,
} ,
} ,
} ,
"interval" : "5m0s" ,
"values" : map [ string ] interface { } {
"image" : map [ string ] interface { } {
"tag" : "5.1.2" ,
} ,
} ,
} ,
2021-06-24 15:06:58 +08:00
} ,
} ,
{
Object : map [ string ] interface { } {
2021-04-11 14:10:16 +08:00
"apiVersion" : "source.toolkit.fluxcd.io/v1beta1" ,
"kind" : "HelmRepository" ,
"metadata" : map [ string ] interface { } {
"name" : fmt . Sprintf ( "%s-%s" , appName , compName ) ,
"namespace" : "default" ,
} ,
"spec" : map [ string ] interface { } {
2021-12-16 15:17:00 +08:00
"url" : "https://charts.kubevela.net/example/" ,
2021-04-11 14:10:16 +08:00
} ,
} ,
2021-06-24 15:06:58 +08:00
} ,
2021-04-11 14:10:16 +08:00
} ,
}
2021-06-24 15:06:58 +08:00
By ( "Verify expected ComponentManifest" )
diff := cmp . Diff ( components [ 0 ] , expectCompManifest )
2021-04-11 14:10:16 +08:00
Expect ( diff ) . ShouldNot ( BeEmpty ( ) )
} )
} )
var _ = Describe ( "Test Kube schematic appfile" , func ( ) {
var (
appName = "test-app"
compName = "test-comp"
)
var testTemplate = func ( ) runtime . RawExtension {
yamlStr := ` apiVersion : apps / v1
kind : Deployment
spec :
selector :
matchLabels :
app : nginx
template :
metadata :
labels :
app : nginx
spec :
containers :
- name : nginx
ports :
- containerPort : 80 `
b , _ := yaml . YAMLToJSON ( [ ] byte ( yamlStr ) )
return runtime . RawExtension { Raw : b }
}
2021-06-24 15:06:58 +08:00
2021-04-11 14:10:16 +08:00
var testAppfile = func ( ) * Appfile {
return & Appfile {
2021-09-12 10:12:46 +08:00
AppRevisionName : appName + "-v1" ,
Name : appName ,
Namespace : "default" ,
RelatedTraitDefinitions : map [ string ] * v1beta1 . TraitDefinition {
"scaler" : {
Spec : v1beta1 . TraitDefinitionSpec { } ,
} ,
} ,
2021-04-11 14:10:16 +08:00
Workloads : [ ] * Workload {
{
Type : "kube-worker" ,
CapabilityCategory : oamtypes . KubeCategory ,
Params : map [ string ] interface { } {
"image" : "nginx:1.14.0" ,
} ,
engine : definition . NewWorkloadAbstractEngine ( compName , pd ) ,
Traits : [ ] * Trait {
{
Name : "scaler" ,
Params : map [ string ] interface { } {
"replicas" : float64 ( 10 ) ,
} ,
engine : definition . NewTraitAbstractEngine ( "scaler" , pd ) ,
Template : `
outputs : scaler : {
apiVersion : "core.oam.dev/v1alpha2"
kind : "ManualScalerTrait"
spec : {
replicaCount : parameter . replicas
}
}
parameter : {
//+short=r
replicas : * 1 | int
}
` ,
} ,
} ,
FullTemplate : & Template {
Kube : & common . Kube {
Template : testTemplate ( ) ,
Parameters : [ ] common . KubeParameter {
{
Name : "image" ,
ValueType : common . StringType ,
Required : pointer . BoolPtr ( true ) ,
FieldPaths : [ ] string { "spec.template.spec.containers[0].image" } ,
} ,
} ,
} ,
2021-05-24 23:32:02 +08:00
Reference : common . WorkloadTypeDescriptor {
Definition : common . WorkloadGVK {
APIVersion : "apps/v1" ,
Kind : "Deployment" ,
} ,
2021-04-11 14:10:16 +08:00
} ,
} ,
} ,
} ,
}
}
It ( "Test generate AppConfig resources from Kube schematic" , func ( ) {
By ( "Generate ApplicationConfiguration and Components" )
2021-06-24 15:06:58 +08:00
comps , err := testAppfile ( ) . GenerateComponentManifests ( )
2021-04-11 14:10:16 +08:00
Expect ( err ) . To ( BeNil ( ) )
2021-06-24 15:06:58 +08:00
expectWorkload := func ( ) * unstructured . Unstructured {
yamlStr := ` apiVersion : apps / v1
kind : Deployment
spec :
selector :
matchLabels :
app : nginx
template :
metadata :
labels :
app : nginx
spec :
containers :
- name : nginx
image : nginx : 1.14 .0
ports :
- containerPort : 80 `
r := & unstructured . Unstructured { }
_ = yaml . Unmarshal ( [ ] byte ( yamlStr ) , r )
return r
} ( )
expectCompManifest := & oamtypes . ComponentManifest {
Name : compName ,
StandardWorkload : expectWorkload ,
Traits : [ ] * unstructured . Unstructured {
{
Object : map [ string ] interface { } {
"apiVersion" : "core.oam.dev/v1alpha2" ,
"kind" : "ManualScalerTrait" ,
"metadata" : map [ string ] interface { } {
"labels" : map [ string ] interface { } {
"app.oam.dev/component" : compName ,
"app.oam.dev/name" : appName ,
"app.oam.dev/appRevision" : appName + "-v1" ,
"trait.oam.dev/type" : "scaler" ,
"trait.oam.dev/resource" : "scaler" ,
2021-04-11 14:10:16 +08:00
} ,
} ,
2021-06-24 15:06:58 +08:00
"spec" : map [ string ] interface { } { "replicaCount" : int64 ( 10 ) } ,
2021-04-11 14:10:16 +08:00
} ,
} ,
} ,
}
By ( "Verify expected Component" )
2021-06-24 15:06:58 +08:00
diff := cmp . Diff ( comps [ 0 ] , expectCompManifest )
2021-04-11 14:10:16 +08:00
Expect ( diff ) . ShouldNot ( BeEmpty ( ) )
} )
It ( "Test missing set required parameter" , func ( ) {
appfile := testAppfile ( )
// remove parameter settings
appfile . Workloads [ 0 ] . Params = nil
2021-06-24 15:06:58 +08:00
_ , err := appfile . GenerateComponentManifests ( )
2021-04-11 14:10:16 +08:00
expectError := errors . WithMessage ( errors . New ( ` require parameter "image" ` ) , "cannot resolve parameter settings" )
diff := cmp . Diff ( expectError , err , test . EquateErrors ( ) )
Expect ( diff ) . Should ( BeEmpty ( ) )
} )
} )
2021-07-22 18:53:30 +08:00
var _ = Describe ( "Test Workflow" , func ( ) {
It ( "generate workflow task runners" , func ( ) {
workflowStepDef := v1beta1 . WorkflowStepDefinition {
Spec : v1beta1 . WorkflowStepDefinitionSpec {
Schematic : & common . Schematic {
CUE : & common . CUE {
Template : `
wait : op . # ConditionalWait & {
continue : true
}
` ,
} ,
} ,
} ,
}
workflowStepDef . Name = "test-wait"
workflowStepDef . Namespace = "default"
err := k8sClient . Create ( context . Background ( ) , & workflowStepDef )
Expect ( err ) . To ( BeNil ( ) )
notCueStepDef := v1beta1 . WorkflowStepDefinition {
Spec : v1beta1 . WorkflowStepDefinitionSpec {
Schematic : & common . Schematic { } ,
} ,
}
notCueStepDef . Name = "not-cue"
notCueStepDef . Namespace = "default"
err = k8sClient . Create ( context . Background ( ) , & notCueStepDef )
Expect ( err ) . To ( BeNil ( ) )
} )
} )
2021-08-29 09:11:10 +08:00
var _ = Describe ( "Test Policy" , func ( ) {
2022-03-07 10:21:00 +08:00
It ( "test generate PolicyWorkloads" , func ( ) {
2021-08-29 09:11:10 +08:00
testAppfile := & Appfile {
Name : "test-app" ,
Namespace : "default" ,
Workloads : [ ] * Workload {
{
Name : "test-comp" ,
Type : "worker" ,
CapabilityCategory : oamtypes . KubeCategory ,
engine : definition . NewWorkloadAbstractEngine ( "test-comp" , pd ) ,
FullTemplate : & Template {
Kube : & common . Kube {
Template : func ( ) runtime . RawExtension {
yamlStr := ` apiVersion : apps / v1
kind : Deployment
spec :
selector :
matchLabels :
app : nginx
template :
metadata :
labels :
app : nginx
spec :
containers :
- name : nginx
ports :
- containerPort : 80 `
b , _ := yaml . YAMLToJSON ( [ ] byte ( yamlStr ) )
return runtime . RawExtension { Raw : b }
} ( ) ,
} ,
} ,
} ,
} ,
2022-03-07 10:21:00 +08:00
PolicyWorkloads : [ ] * Workload {
2021-08-29 09:11:10 +08:00
{
Name : "test-policy" ,
Type : "test-policy" ,
Params : map [ string ] interface { } {
"boundComponents" : [ ] string { "test-comp" } ,
} ,
FullTemplate : & Template { TemplateStr : ` output : {
apiVersion : "core.oam.dev/v1alpha2"
kind : "HealthScope"
spec : {
2021-09-12 10:12:46 +08:00
for k , v in parameter . boundComponents {
2021-08-29 09:11:10 +08:00
compName : v
workload : {
apiVersion : context . artifacts [ v ] . workload . apiVersion
kind : context . artifacts [ v ] . workload . kind
name : v
}
} ,
}
}
parameter : {
boundComponents : [ ... string ]
} ` } ,
engine : definition . NewWorkloadAbstractEngine ( "test-policy" , pd ) ,
} ,
} ,
2021-11-08 23:11:50 +08:00
app : & v1beta1 . Application { } ,
2021-08-29 09:11:10 +08:00
}
_ , err := testAppfile . GenerateComponentManifests ( )
Expect ( err ) . Should ( BeNil ( ) )
2022-03-07 10:21:00 +08:00
testAppfile . parser = & Parser { client : k8sClient }
2022-03-24 14:40:19 +08:00
gotPolicies , err := testAppfile . GeneratePolicyManifests ( context . Background ( ) )
2021-08-29 09:11:10 +08:00
Expect ( err ) . Should ( BeNil ( ) )
Expect ( len ( gotPolicies ) ) . ShouldNot ( Equal ( 0 ) )
expectPolicy := unstructured . Unstructured {
Object : map [ string ] interface { } {
"spec" : map [ string ] interface { } {
"compName" : "test-comp" ,
"workload" : map [ string ] interface { } {
"name" : "test-comp" ,
"apiVersion" : "apps/v1" ,
"kind" : "Deployment" ,
} ,
} ,
"metadata" : map [ string ] interface { } {
"name" : "test-policy" ,
"namespace" : "default" ,
"labels" : map [ string ] interface { } {
"app.oam.dev/name" : "test-app" ,
"app.oam.dev/component" : "test-policy" ,
"app.oam.dev/appRevision" : "" ,
"workload.oam.dev/type" : "test-policy" ,
} ,
} ,
"apiVersion" : "core.oam.dev/v1alpha2" ,
"kind" : "HealthScope" ,
} ,
}
Expect ( len ( gotPolicies ) ) . ShouldNot ( Equal ( 0 ) )
gotPolicy := gotPolicies [ 0 ]
Expect ( cmp . Diff ( gotPolicy . Object , expectPolicy . Object ) ) . Should ( BeEmpty ( ) )
} )
} )
2021-04-30 16:28:00 +08:00
var _ = Describe ( "Test Terraform schematic appfile" , func ( ) {
It ( "workload capability is Terraform" , func ( ) {
var (
ns = "default"
compName = "sample-db"
appName = "webapp"
revision = "v1"
configuration = `
module "rds" {
source = "terraform-alicloud-modules/rds/alicloud"
engine = "MySQL"
engine_version = "8.0"
instance_type = "rds.mysql.c1.large"
instance_storage = "20"
instance_name = var . instance_name
account_name = var . account_name
password = var . password
}
output "DB_NAME" {
value = module . rds . this_db_instance_name
}
output "DB_USER" {
value = module . rds . this_db_database_account
}
output "DB_PORT" {
value = module . rds . this_db_instance_port
}
output "DB_HOST" {
value = module . rds . this_db_instance_connection_string
}
output "DB_PASSWORD" {
value = module . rds . this_db_instance_port
}
variable "instance_name" {
description = "RDS instance name"
type = string
default = "poc"
}
variable "account_name" {
description = "RDS instance user account name"
type = "string"
default = "oam"
}
variable "password" {
description = "RDS instance account password"
type = "string"
default = "Xyfff83jfewGGfaked"
}
`
)
wl := & Workload {
Name : "sample-db" ,
FullTemplate : & Template {
Terraform : & common . Terraform {
Configuration : configuration ,
Type : "hcl" ,
} ,
} ,
CapabilityCategory : oamtypes . TerraformCategory ,
Params : map [ string ] interface { } {
"account_name" : "oamtest" ,
"writeConnectionSecretToRef" : map [ string ] interface { } {
"name" : "db" ,
} ,
2021-08-30 11:43:20 +08:00
model . OutputSecretName : "db-conn" ,
2021-04-30 16:28:00 +08:00
} ,
}
af := & Appfile {
2021-09-12 10:12:46 +08:00
Workloads : [ ] * Workload { wl } ,
Name : appName ,
AppRevisionName : revision ,
Namespace : ns ,
2021-04-30 16:28:00 +08:00
}
variable := map [ string ] interface { } { "account_name" : "oamtest" }
data , _ := json . Marshal ( variable )
raw := & runtime . RawExtension { }
raw . Raw = data
workload := terraformapi . Configuration {
TypeMeta : metav1 . TypeMeta {
APIVersion : "terraform.core.oam.dev/v1beta1" ,
Kind : "Configuration" ,
} ,
ObjectMeta : metav1 . ObjectMeta {
Labels : map [ string ] string {
"app.oam.dev/appRevision" : "v1" ,
"app.oam.dev/component" : "sample-db" ,
"app.oam.dev/name" : "webapp" ,
"workload.oam.dev/type" : "" ,
} ,
Name : "sample-db" ,
Namespace : "default" ,
} ,
Spec : terraformapi . ConfigurationSpec {
2021-12-02 15:45:50 +08:00
HCL : configuration ,
Variable : raw ,
2021-04-30 16:28:00 +08:00
} ,
Status : terraformapi . ConfigurationStatus { } ,
}
2021-12-02 15:45:50 +08:00
workload . Spec . WriteConnectionSecretToReference = & terraformtypes . SecretReference { Name : "db" , Namespace : "default" }
2021-04-30 16:28:00 +08:00
2021-06-24 15:06:58 +08:00
expectCompManifest := & oamtypes . ComponentManifest {
Name : compName ,
StandardWorkload : func ( ) * unstructured . Unstructured {
r , _ := util . Object2Unstructured ( workload )
return r
} ( ) ,
2021-04-30 16:28:00 +08:00
}
2021-06-24 15:06:58 +08:00
comps , err := af . GenerateComponentManifests ( )
diff := cmp . Diff ( comps [ 0 ] , expectCompManifest )
2021-04-30 16:28:00 +08:00
Expect ( diff ) . ShouldNot ( BeEmpty ( ) )
Expect ( err ) . Should ( BeNil ( ) )
} )
} )
2021-04-11 14:10:16 +08:00
func TestResolveKubeParameters ( t * testing . T ) {
stringParam := & common . KubeParameter {
Name : "strParam" ,
ValueType : common . StringType ,
FieldPaths : [ ] string { "spec" } ,
}
requiredParam := & common . KubeParameter {
Name : "reqParam" ,
Required : pointer . BoolPtr ( true ) ,
ValueType : common . StringType ,
FieldPaths : [ ] string { "spec" } ,
}
tests := map [ string ] struct {
reason string
params [ ] common . KubeParameter
settings map [ string ] interface { }
want paramValueSettings
wantErr error
} {
"EmptyParam" : {
reason : "Empty value settings and no error should be returned" ,
want : make ( paramValueSettings ) ,
} ,
"UnsupportedParam" : {
reason : "An error shoulde be returned because of unsupported param" ,
params : [ ] common . KubeParameter { * stringParam } ,
settings : map [ string ] interface { } { "unsupported" : "invalid parameter" } ,
want : nil ,
wantErr : errors . Errorf ( "unsupported parameter %q" , "unsupported" ) ,
} ,
"MissingRequiredParam" : {
reason : "An error should be returned because of missing required param" ,
params : [ ] common . KubeParameter { * stringParam , * requiredParam } ,
settings : map [ string ] interface { } { "strParam" : "string" } ,
want : nil ,
wantErr : errors . Errorf ( "require parameter %q" , "reqParam" ) ,
} ,
"Succeed" : {
reason : "No error should be returned" ,
params : [ ] common . KubeParameter { * stringParam , * requiredParam } ,
settings : map [ string ] interface { } { "strParam" : "test" , "reqParam" : "test" } ,
want : paramValueSettings {
"strParam" : paramValueSetting {
Value : "test" ,
ValueType : common . StringType ,
FieldPaths : stringParam . FieldPaths ,
} ,
"reqParam" : paramValueSetting {
Value : "test" ,
ValueType : common . StringType ,
FieldPaths : requiredParam . FieldPaths ,
} ,
} ,
wantErr : nil ,
} ,
}
for tcName , tc := range tests {
t . Run ( tcName , func ( t * testing . T ) {
result , err := resolveKubeParameters ( tc . params , tc . settings )
if diff := cmp . Diff ( tc . want , result ) ; diff != "" {
t . Fatalf ( "\nresolveKubeParameters(...)(...) -want +get \nreason:%s\n%s\n" , tc . reason , diff )
}
if diff := cmp . Diff ( tc . wantErr , err , test . EquateErrors ( ) ) ; diff != "" {
t . Fatalf ( "\nresolveKubeParameters(...)(...) -want +get \nreason:%s\n%s\n" , tc . reason , diff )
}
} )
}
}
func TestSetParameterValuesToKubeObj ( t * testing . T ) {
tests := map [ string ] struct {
reason string
obj unstructured . Unstructured
values paramValueSettings
wantObj unstructured . Unstructured
wantErr error
} {
"InvalidStringType" : {
reason : "An error should be returned" ,
values : paramValueSettings {
"strParam" : paramValueSetting {
Value : int32 ( 100 ) ,
ValueType : common . StringType ,
FieldPaths : [ ] string { "spec.test" } ,
} ,
} ,
wantErr : errors . Errorf ( errInvalidValueType , common . StringType ) ,
} ,
"InvalidNumberType" : {
reason : "An error should be returned" ,
values : paramValueSettings {
"intParam" : paramValueSetting {
Value : "test" ,
ValueType : common . NumberType ,
FieldPaths : [ ] string { "spec.test" } ,
} ,
} ,
wantErr : errors . Errorf ( errInvalidValueType , common . NumberType ) ,
} ,
"InvalidBoolType" : {
reason : "An error should be returned" ,
values : paramValueSettings {
"boolParam" : paramValueSetting {
Value : "test" ,
ValueType : common . BooleanType ,
FieldPaths : [ ] string { "spec.test" } ,
} ,
} ,
wantErr : errors . Errorf ( errInvalidValueType , common . BooleanType ) ,
} ,
"InvalidFieldPath" : {
reason : "An error should be returned" ,
values : paramValueSettings {
"strParam" : paramValueSetting {
Value : "test" ,
ValueType : common . StringType ,
FieldPaths : [ ] string { "spec[.test" } , // a invalid field path
} ,
} ,
wantErr : errors . Wrap ( errors . New ( ` cannot parse path "spec[.test": unterminated '[' at position 4 ` ) ,
` cannot set parameter "strParam" to field "spec[.test" ` ) ,
} ,
"Succeed" : {
reason : "No error should be returned" ,
obj : unstructured . Unstructured { Object : make ( map [ string ] interface { } ) } ,
values : paramValueSettings {
"strParam" : paramValueSetting {
Value : "test" ,
ValueType : common . StringType ,
FieldPaths : [ ] string { "spec.strField" } ,
} ,
"intParam" : paramValueSetting {
Value : 10 ,
ValueType : common . NumberType ,
FieldPaths : [ ] string { "spec.intField" } ,
} ,
"floatParam" : paramValueSetting {
Value : float64 ( 10.01 ) ,
ValueType : common . NumberType ,
FieldPaths : [ ] string { "spec.floatField" } ,
} ,
"boolParam" : paramValueSetting {
Value : true ,
ValueType : common . BooleanType ,
FieldPaths : [ ] string { "spec.boolField" } ,
} ,
} ,
wantObj : unstructured . Unstructured { Object : map [ string ] interface { } {
"spec" : map [ string ] interface { } {
"strField" : "test" ,
"intField" : int64 ( 10 ) ,
"floatField" : float64 ( 10.01 ) ,
"boolField" : true ,
} ,
} } ,
} ,
}
for tcName , tc := range tests {
t . Run ( tcName , func ( t * testing . T ) {
obj := tc . obj . DeepCopy ( )
err := setParameterValuesToKubeObj ( obj , tc . values )
if diff := cmp . Diff ( tc . wantObj , * obj ) ; diff != "" {
t . Errorf ( "\nsetParameterValuesToKubeObj(...)error -want +get \nreason:%s\n%s\n" , tc . reason , diff )
}
if diff := cmp . Diff ( tc . wantErr , err , test . EquateErrors ( ) ) ; diff != "" {
t . Errorf ( "\nsetParameterValuesToKubeObj(...)error -want +get \nreason:%s\n%s\n" , tc . reason , diff )
}
} )
}
}
2021-04-30 16:28:00 +08:00
var _ = Describe ( "Test evalWorkloadWithContext" , func ( ) {
It ( "workload capability is Terraform" , func ( ) {
var (
ns = "default"
compName = "sample-db"
err error
)
type appArgs struct {
wl * Workload
appName string
revision string
}
args := appArgs {
wl : & Workload {
Name : "sample-db" ,
FullTemplate : & Template {
Terraform : & common . Terraform {
Configuration : `
module "rds" {
source = "terraform-alicloud-modules/rds/alicloud"
engine = "MySQL"
engine_version = "8.0"
instance_type = "rds.mysql.c1.large"
instance_storage = "20"
instance_name = var . instance_name
account_name = var . account_name
password = var . password
}
output "DB_NAME" {
value = module . rds . this_db_instance_name
}
output "DB_USER" {
value = module . rds . this_db_database_account
}
output "DB_PORT" {
value = module . rds . this_db_instance_port
}
output "DB_HOST" {
value = module . rds . this_db_instance_connection_string
}
output "DB_PASSWORD" {
value = module . rds . this_db_instance_port
}
variable "instance_name" {
description = "RDS instance name"
type = string
default = "poc"
}
variable "account_name" {
description = "RDS instance user account name"
type = "string"
default = "oam"
}
variable "password" {
description = "RDS instance account password"
type = "string"
default = "Xyfff83jfewGGfaked"
}
` ,
Type : "hcl" ,
} ,
} ,
CapabilityCategory : oamtypes . TerraformCategory ,
engine : definition . NewWorkloadAbstractEngine ( compName , pd ) ,
Params : map [ string ] interface { } {
"variable" : map [ string ] interface { } {
"account_name" : "oamtest" ,
} ,
} ,
} ,
appName : "webapp" ,
revision : "v1" ,
}
2022-02-28 10:30:55 +08:00
ctxData := GenerateContextDataFromAppFile ( & Appfile {
Name : args . appName ,
Namespace : ns ,
AppRevisionName : args . revision ,
} , args . wl . Name )
pCtx := NewBasicContext ( ctxData , args . wl . Params )
2021-06-24 15:06:58 +08:00
comp , err := evalWorkloadWithContext ( pCtx , args . wl , ns , args . appName , compName )
Expect ( comp . StandardWorkload ) . ShouldNot ( BeNil ( ) )
Expect ( comp . Name ) . Should ( Equal ( "" ) )
2021-04-30 16:28:00 +08:00
Expect ( err ) . Should ( BeNil ( ) )
} )
} )
func TestGenerateTerraformConfigurationWorkload ( t * testing . T ) {
var (
name = "oss"
ns = "default"
variable = map [ string ] interface { } { "acl" : "private" }
)
ch := make ( chan string )
badParam := map [ string ] interface { } { "abc" : ch }
_ , badParamMarshalError := json . Marshal ( badParam )
type args struct {
writeConnectionSecretToRef * terraformtypes . SecretReference
json string
hcl string
2021-09-29 14:58:27 +08:00
remote string
2021-04-30 16:28:00 +08:00
params map [ string ] interface { }
2021-10-08 11:35:52 +08:00
providerRef * terraformtypes . Reference
2021-04-30 16:28:00 +08:00
}
type want struct {
err error
}
testcases := map [ string ] struct {
args args
want want
} {
"json workload with secret" : {
args : args {
json : "abc" ,
params : map [ string ] interface { } { "acl" : "private" ,
"writeConnectionSecretToRef" : map [ string ] interface { } { "name" : "oss" , "namespace" : "" } } ,
writeConnectionSecretToRef : & terraformtypes . SecretReference { Name : "oss" , Namespace : "default" } ,
} ,
want : want { err : nil } } ,
"valid hcl workload" : {
args : args {
hcl : "abc" ,
params : map [ string ] interface { } { "acl" : "private" ,
"writeConnectionSecretToRef" : map [ string ] interface { } { "name" : "oss" , "namespace" : "default" } } ,
writeConnectionSecretToRef : & terraformtypes . SecretReference { Name : "oss" , Namespace : "default" } ,
} ,
want : want { err : nil } } ,
2021-09-29 14:58:27 +08:00
"remote hcl workload" : {
args : args {
remote : "https://xxx/a.git" ,
params : map [ string ] interface { } { "acl" : "private" ,
"writeConnectionSecretToRef" : map [ string ] interface { } { "name" : "oss" , "namespace" : "default" } } ,
writeConnectionSecretToRef : & terraformtypes . SecretReference { Name : "oss" , Namespace : "default" } ,
} ,
want : want { err : nil } } ,
2021-04-30 16:28:00 +08:00
"workload's TF configuration is empty" : {
args : args {
params : variable ,
} ,
want : want { err : errors . New ( errTerraformConfigurationIsNotSet ) } ,
} ,
"workload's params is bad" : {
args : args {
params : badParam ,
hcl : "abc" ,
} ,
2021-10-08 11:35:52 +08:00
want : want { err : errors . Wrap ( badParamMarshalError , errFailToConvertTerraformComponentProperties ) } ,
} ,
2022-01-06 19:02:03 +08:00
"terraform workload has a provider reference, but parameters are bad" : {
2021-10-08 11:35:52 +08:00
args : args {
params : badParam ,
hcl : "abc" ,
providerRef : & terraformtypes . Reference { Name : "azure" , Namespace : "default" } ,
} ,
want : want { err : errors . Wrap ( badParamMarshalError , errFailToConvertTerraformComponentProperties ) } ,
} ,
2022-01-06 19:02:03 +08:00
"terraform workload has a provider reference" : {
args : args {
params : variable ,
hcl : "variable \"name\" {\n description = \"Name to be used on all resources as prefix. Default to 'TF-Module-EIP'.\"\n default = \"TF-Module-EIP\"\n type = string\n }" ,
providerRef : & terraformtypes . Reference { Name : "aws" , Namespace : "default" } ,
} ,
want : want { err : nil } ,
} ,
2021-04-30 16:28:00 +08:00
}
for tcName , tc := range testcases {
var (
template * Template
configSpec terraformapi . ConfigurationSpec
)
data , _ := json . Marshal ( variable )
raw := & runtime . RawExtension { }
raw . Raw = data
if tc . args . hcl != "" {
template = & Template {
Terraform : & common . Terraform {
Configuration : tc . args . hcl ,
Type : "hcl" ,
} ,
}
configSpec = terraformapi . ConfigurationSpec {
2021-12-02 15:45:50 +08:00
HCL : tc . args . hcl ,
Variable : raw ,
2021-04-30 16:28:00 +08:00
}
2021-12-02 15:45:50 +08:00
configSpec . WriteConnectionSecretToReference = tc . args . writeConnectionSecretToRef
2021-04-30 16:28:00 +08:00
}
if tc . args . json != "" {
template = & Template {
Terraform : & common . Terraform {
Configuration : tc . args . json ,
Type : "json" ,
} ,
}
configSpec = terraformapi . ConfigurationSpec {
2021-12-02 15:45:50 +08:00
JSON : tc . args . json ,
Variable : raw ,
2021-04-30 16:28:00 +08:00
}
2021-12-02 15:45:50 +08:00
configSpec . WriteConnectionSecretToReference = tc . args . writeConnectionSecretToRef
2021-04-30 16:28:00 +08:00
}
2021-09-29 14:58:27 +08:00
if tc . args . remote != "" {
template = & Template {
Terraform : & common . Terraform {
Configuration : tc . args . remote ,
Type : "remote" ,
} ,
}
configSpec = terraformapi . ConfigurationSpec {
2021-12-02 15:45:50 +08:00
Remote : tc . args . remote ,
Variable : raw ,
2021-09-29 14:58:27 +08:00
}
2021-12-02 15:45:50 +08:00
configSpec . WriteConnectionSecretToReference = tc . args . writeConnectionSecretToRef
2021-09-29 14:58:27 +08:00
}
if tc . args . hcl == "" && tc . args . json == "" && tc . args . remote == "" {
2021-04-30 16:28:00 +08:00
template = & Template {
Terraform : & common . Terraform { } ,
}
configSpec = terraformapi . ConfigurationSpec {
2021-12-02 15:45:50 +08:00
Variable : raw ,
2021-04-30 16:28:00 +08:00
}
2021-12-02 15:45:50 +08:00
configSpec . WriteConnectionSecretToReference = tc . args . writeConnectionSecretToRef
2021-04-30 16:28:00 +08:00
}
2021-10-08 11:35:52 +08:00
if tc . args . providerRef != nil {
2022-01-06 19:02:03 +08:00
tf := & common . Terraform { }
tf . ProviderReference = tc . args . providerRef
template . ComponentDefinition = & v1beta1 . ComponentDefinition {
Spec : v1beta1 . ComponentDefinitionSpec {
Schematic : & common . Schematic {
Terraform : tf ,
} ,
} ,
}
configSpec . ProviderReference = tc . args . providerRef
2021-10-08 11:35:52 +08:00
}
2021-04-30 16:28:00 +08:00
wl := & Workload {
FullTemplate : template ,
Name : name ,
Params : tc . args . params ,
}
got , err := generateTerraformConfigurationWorkload ( wl , ns )
if diff := cmp . Diff ( tc . want . err , err , test . EquateErrors ( ) ) ; diff != "" {
t . Errorf ( "\n%s\ngenerateTerraformConfigurationWorkload(...): -want error, +got error:\n%s\n" , tcName , diff )
}
if err == nil {
tfConfiguration := terraformapi . Configuration {
TypeMeta : metav1 . TypeMeta { APIVersion : "terraform.core.oam.dev/v1beta1" , Kind : "Configuration" } ,
ObjectMeta : metav1 . ObjectMeta { Name : name , Namespace : ns } ,
Spec : configSpec ,
}
rawConf := util . Object2RawExtension ( tfConfiguration )
2021-10-13 16:16:53 +08:00
wantWL , _ := util . RawExtension2Unstructured ( rawConf )
2021-04-30 16:28:00 +08:00
if diff := cmp . Diff ( wantWL , got ) ; diff != "" {
t . Errorf ( "\n%s\ngenerateTerraformConfigurationWorkload(...): -want, +got:\n%s\n" , tcName , diff )
}
}
}
}
2021-05-13 21:46:45 +08:00
2021-07-08 15:16:55 +08:00
func TestGenerateCUETemplate ( t * testing . T ) {
var testCorrectTemplate = func ( ) runtime . RawExtension {
yamlStr := ` apiVersion : apps / v1
kind : Deployment
spec :
selector :
matchLabels :
app : nginx
template :
metadata :
labels :
app : nginx
spec :
containers :
- name : nginx
ports :
- containerPort : 80 `
b , _ := yaml . YAMLToJSON ( [ ] byte ( yamlStr ) )
return runtime . RawExtension { Raw : b }
}
var testErrorTemplate = func ( ) runtime . RawExtension {
yamlStr := ` apiVersion : apps / v1
kind : Deployment
spec :
template :
selector :
matchLabels :
app : nginx
`
b , _ := yaml . YAMLToJSON ( [ ] byte ( yamlStr ) )
return runtime . RawExtension { Raw : b }
}
testcases := map [ string ] struct {
workload * Workload
expectData string
hasError bool
errInfo string
} { "Kube workload with Correct template" : {
workload : & Workload {
FullTemplate : & Template {
Kube : & common . Kube {
Template : testCorrectTemplate ( ) ,
Parameters : [ ] common . KubeParameter {
{
Name : "image" ,
ValueType : common . StringType ,
Required : pointer . BoolPtr ( true ) ,
FieldPaths : [ ] string { "spec.template.spec.containers[0].image" } ,
} ,
} ,
} ,
Reference : common . WorkloadTypeDescriptor {
Definition : common . WorkloadGVK {
APIVersion : "apps/v1" ,
Kind : "Deployment" ,
} ,
} ,
} ,
Params : map [ string ] interface { } {
"image" : "nginx:1.14.0" ,
} ,
CapabilityCategory : oamtypes . KubeCategory ,
} ,
expectData : `
output : {
apiVersion : "apps/v1"
kind : "Deployment"
spec : {
selector : {
matchLabels : {
app : "nginx"
}
}
template : {
spec : {
containers : [ {
name : "nginx"
image : "nginx:1.14.0"
} ]
ports : [ {
containerPort : 80
} ]
}
metadata : {
labels : {
app : "nginx"
}
}
}
}
} ` ,
hasError : false ,
} , "Kube workload with wrong template" : {
workload : & Workload {
FullTemplate : & Template {
Kube : & common . Kube {
Template : testErrorTemplate ( ) ,
Parameters : [ ] common . KubeParameter {
{
Name : "image" ,
ValueType : common . StringType ,
Required : pointer . BoolPtr ( true ) ,
FieldPaths : [ ] string { "spec.template.spec.containers[0].image" } ,
} ,
} ,
} ,
Reference : common . WorkloadTypeDescriptor {
Definition : common . WorkloadGVK {
APIVersion : "apps/v1" ,
Kind : "Deployment" ,
} ,
} ,
} ,
Params : map [ string ] interface { } {
"image" : "nginx:1.14.0" ,
} ,
CapabilityCategory : oamtypes . KubeCategory ,
} ,
hasError : true ,
errInfo : "cannot decode Kube template into K8s object: unexpected end of JSON input" ,
} , "Kube workload with wrong parameter" : {
workload : & Workload {
FullTemplate : & Template {
Kube : & common . Kube {
Template : testCorrectTemplate ( ) ,
Parameters : [ ] common . KubeParameter {
{
Name : "image" ,
ValueType : common . StringType ,
Required : pointer . BoolPtr ( true ) ,
FieldPaths : [ ] string { "spec.template.spec.containers[0].image" } ,
} ,
} ,
} ,
Reference : common . WorkloadTypeDescriptor {
Definition : common . WorkloadGVK {
APIVersion : "apps/v1" ,
Kind : "Deployment" ,
} ,
} ,
} ,
Params : map [ string ] interface { } {
"unsupported" : "invalid parameter" ,
} ,
CapabilityCategory : oamtypes . KubeCategory ,
} ,
hasError : true ,
errInfo : "cannot resolve parameter settings: unsupported parameter \"unsupported\"" ,
} , "Helm workload with correct reference" : {
workload : & Workload {
FullTemplate : & Template {
Reference : common . WorkloadTypeDescriptor {
Definition : common . WorkloadGVK {
APIVersion : "app/v1" ,
Kind : "deployment" ,
} ,
} ,
} ,
CapabilityCategory : oamtypes . HelmCategory ,
} ,
hasError : false ,
expectData : `
output : {
apiVersion : "app/v1"
kind : "deployment"
} ` ,
} , "Helm workload with wrong reference" : {
workload : & Workload {
FullTemplate : & Template {
Reference : common . WorkloadTypeDescriptor {
Definition : common . WorkloadGVK {
APIVersion : "app@//v1" ,
Kind : "deployment" ,
} ,
} ,
} ,
CapabilityCategory : oamtypes . HelmCategory ,
} ,
hasError : true ,
errInfo : "unexpected GroupVersion string: app@//v1" ,
} }
for _ , tc := range testcases {
template , err := GenerateCUETemplate ( tc . workload )
assert . Equal ( t , err != nil , tc . hasError )
if tc . hasError {
assert . Equal ( t , tc . errInfo , err . Error ( ) )
continue
}
assert . Equal ( t , tc . expectData , template )
}
}
2021-08-29 09:11:10 +08:00
func TestPrepareArtifactsData ( t * testing . T ) {
compManifests := [ ] * oamtypes . ComponentManifest {
2021-09-12 10:12:46 +08:00
{
2021-08-29 09:11:10 +08:00
Name : "readyComp" ,
Namespace : "ns" ,
RevisionName : "readyComp-v1" ,
StandardWorkload : & unstructured . Unstructured { Object : map [ string ] interface { } {
"fake" : "workload" ,
} } ,
Traits : func ( ) [ ] * unstructured . Unstructured {
ingressYAML := ` apiVersion : networking . k8s . io / v1
kind : Ingress
metadata :
labels :
trait . oam . dev / resource : ingress
trait . oam . dev / type : ingress
namespace : default
spec :
rules :
- host : testsvc . example . com `
ingress := & unstructured . Unstructured { }
_ = yaml . Unmarshal ( [ ] byte ( ingressYAML ) , ingress )
svcYAML := ` apiVersion : v1
kind : Service
metadata :
labels :
trait . oam . dev / resource : service
trait . oam . dev / type : ingress
namespace : default
spec :
clusterIP : 10.96 .185 .119
selector :
app . oam . dev / component : express - server
type : ClusterIP `
svc := & unstructured . Unstructured { }
_ = yaml . Unmarshal ( [ ] byte ( svcYAML ) , svc )
return [ ] * unstructured . Unstructured { ingress , svc }
} ( ) ,
} ,
}
gotArtifacts := prepareArtifactsData ( compManifests )
gotWorkload , _ , err := unstructured . NestedMap ( gotArtifacts , "readyComp" , "workload" )
assert . NilError ( t , err )
diff := cmp . Diff ( gotWorkload , map [ string ] interface { } { "fake" : string ( "workload" ) } )
assert . Equal ( t , diff , "" )
_ , gotIngress , err := unstructured . NestedMap ( gotArtifacts , "readyComp" , "traits" , "ingress" , "ingress" )
assert . NilError ( t , err )
if ! gotIngress {
t . Fatalf ( "cannot get ingress trait" )
}
_ , gotSvc , err := unstructured . NestedMap ( gotArtifacts , "readyComp" , "traits" , "ingress" , "service" )
assert . NilError ( t , err )
if ! gotSvc {
t . Fatalf ( "cannot get service trait" )
}
}
2022-02-08 16:26:16 +08:00
func TestBaseGenerateComponent ( t * testing . T ) {
var appName = "test-app"
var ns = "test-ns"
var traitName = "mytrait"
var wlName = "my-wl-1"
2022-02-28 10:30:55 +08:00
var workflowName = "my-wf"
var publishVersion = "123"
ctxData := GenerateContextDataFromAppFile ( & Appfile {
Name : appName ,
Namespace : ns ,
AppAnnotations : map [ string ] string {
oam . AnnotationWorkflowName : workflowName ,
oam . AnnotationPublishVersion : publishVersion ,
} ,
} , wlName )
pContext := NewBasicContext ( ctxData , nil )
2022-02-08 16:26:16 +08:00
base := `
apiVersion : "apps/v1"
kind : "Deployment"
spec : {
template : {
spec : containers : [ {
image : "nginx"
} ]
}
}
`
var r cue . Runtime
inst , err := r . Compile ( "-" , base )
assert . NilError ( t , err )
bs , _ := model . NewBase ( inst . Value ( ) )
err = pContext . SetBase ( bs )
assert . NilError ( t , err )
tr := & Trait {
Name : traitName ,
engine : definition . NewTraitAbstractEngine ( traitName , nil ) ,
Template : ` outputs : mytrait : {
if context . componentType == "stateless" {
kind : "Deployment"
}
if context . componentType == "stateful" {
kind : "StatefulSet"
}
name : context . name
envSourceContainerName : context . name
2022-02-28 10:30:55 +08:00
workflowName : context . workflowName
publishVersion : context . publishVersion
2022-02-08 16:26:16 +08:00
} ` ,
}
wl := & Workload { Type : "stateful" , Traits : [ ] * Trait { tr } }
cm , err := baseGenerateComponent ( pContext , wl , appName , ns )
assert . NilError ( t , err )
assert . Equal ( t , cm . Traits [ 0 ] . Object [ "kind" ] , "StatefulSet" )
2022-02-28 10:30:55 +08:00
assert . Equal ( t , cm . Traits [ 0 ] . Object [ "workflowName" ] , workflowName )
assert . Equal ( t , cm . Traits [ 0 ] . Object [ "publishVersion" ] , publishVersion )
2022-02-08 16:26:16 +08:00
}
2022-03-21 12:02:30 +08:00
var _ = Describe ( "Test use context.appLabels& context.appAnnotations in componentDefinition " , func ( ) {
It ( "Test generate AppConfig resources from " , func ( ) {
af := & Appfile {
Name : "app" ,
Namespace : "ns" ,
AppLabels : map [ string ] string {
"lk1" : "lv1" ,
"lk2" : "lv2" ,
} ,
AppAnnotations : map [ string ] string {
"ak1" : "av1" ,
"ak2" : "av2" ,
} ,
Workloads : [ ] * Workload {
{
Name : "comp1" ,
Type : "deployment" ,
Params : map [ string ] interface { } {
"image" : "busybox" ,
"cmd" : [ ] interface { } { "sleep" , "1000" } ,
} ,
engine : definition . NewWorkloadAbstractEngine ( "myweb" , pd ) ,
FullTemplate : & Template {
TemplateStr : `
output : {
apiVersion : "apps/v1"
kind : "Deployment"
spec : {
selector : matchLabels : {
"app.oam.dev/component" : context . name
}
template : {
metadata : {
labels : {
if context . appLabels != _ | _ {
context . appLabels
}
}
annotations : {
if context . appAnnotations != _ | _ {
context . appAnnotations
}
}
}
spec : {
containers : [ {
name : context . name
image : parameter . image
if parameter [ "cmd" ] != _ | _ {
command : parameter . cmd
}
} ]
}
}
selector :
matchLabels :
"app.oam.dev/component" : context . name
}
}
parameter : {
// +usage=Which image would you like to use for your service
// +short=i
image : string
cmd ? : [ ... string ]
} ` } ,
} ,
} ,
}
By ( "Generate ComponentManifests" )
componentManifests , err := af . GenerateComponentManifests ( )
Expect ( err ) . To ( BeNil ( ) )
By ( "Verify expected ComponentManifest" )
deployment := & appsv1 . Deployment { }
runtime . DefaultUnstructuredConverter . FromUnstructured ( componentManifests [ 0 ] . StandardWorkload . Object , deployment )
labels := deployment . Spec . Template . Labels
annotations := deployment . Spec . Template . Annotations
Expect ( cmp . Diff ( len ( labels ) , 2 ) ) . Should ( BeEmpty ( ) )
Expect ( cmp . Diff ( len ( annotations ) , 2 ) ) . Should ( BeEmpty ( ) )
Expect ( cmp . Diff ( labels [ "lk1" ] , "lv1" ) ) . Should ( BeEmpty ( ) )
Expect ( cmp . Diff ( annotations [ "ak1" ] , "av1" ) ) . Should ( BeEmpty ( ) )
} )
} )