github.com/kubevela/workflow@v0.6.0/pkg/cue/model/instance.go (about) 1 /* 2 Copyright 2022 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 model 18 19 import ( 20 "cuelang.org/go/cue" 21 "github.com/pkg/errors" 22 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 23 "k8s.io/klog/v2" 24 25 "github.com/kubevela/workflow/pkg/cue/model/sets" 26 ) 27 28 // Instance defines Model Interface 29 type Instance interface { 30 String() (string, error) 31 Value() cue.Value 32 Unstructured() (*unstructured.Unstructured, error) 33 IsBase() bool 34 Unify(other cue.Value, options ...sets.UnifyOption) error 35 Compile() ([]byte, error) 36 } 37 38 type instance struct { 39 v cue.Value 40 base bool 41 } 42 43 // String return instance's cue format string 44 func (inst *instance) String() (string, error) { 45 return sets.ToString(inst.v) 46 } 47 48 func (inst *instance) Value() cue.Value { 49 return inst.v 50 } 51 52 // IsBase indicate whether the instance is base model 53 func (inst *instance) IsBase() bool { 54 return inst.base 55 } 56 57 func (inst *instance) Compile() ([]byte, error) { 58 if err := inst.v.Err(); err != nil { 59 return nil, err 60 } 61 // compiled object should be final and concrete value 62 if err := inst.v.Validate(cue.Concrete(true), cue.Final()); err != nil { 63 return nil, err 64 } 65 return inst.v.MarshalJSON() 66 } 67 68 // Unstructured convert cue values to unstructured.Unstructured 69 // TODO(wonderflow): will it be better if we try to decode it to concrete object(such as K8s Deployment) by using runtime.Schema? 70 func (inst *instance) Unstructured() (*unstructured.Unstructured, error) { 71 jsonv, err := inst.Compile() 72 if err != nil { 73 klog.ErrorS(err, "failed to have the workload/trait unstructured", "Definition", inst.v) 74 return nil, errors.Wrap(err, "failed to have the workload/trait unstructured") 75 } 76 o := &unstructured.Unstructured{} 77 if err := o.UnmarshalJSON(jsonv); err != nil { 78 return nil, err 79 } 80 return o, nil 81 } 82 83 // Unify implement unity operations between instances 84 func (inst *instance) Unify(other cue.Value, options ...sets.UnifyOption) error { 85 pv, err := sets.StrategyUnify(inst.v, other, options...) 86 if err != nil { 87 return err 88 } 89 inst.v = pv 90 return nil 91 } 92 93 // NewBase create a base instance 94 func NewBase(v cue.Value) (Instance, error) { 95 return &instance{ 96 v: v, 97 base: true, 98 }, nil 99 } 100 101 // NewOther create a non-base instance 102 func NewOther(v cue.Value) (Instance, error) { 103 return &instance{ 104 v: v, 105 }, nil 106 }