github.skymusic.top/operator-framework/operator-sdk@v0.8.2/pkg/test/resource_creator.go (about) 1 // Copyright 2018 The Operator-SDK Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package test 16 17 import ( 18 goctx "context" 19 "fmt" 20 "io/ioutil" 21 "time" 22 23 "github.com/ghodss/yaml" 24 "github.com/operator-framework/operator-sdk/internal/util/yamlutil" 25 core "k8s.io/api/core/v1" 26 apierrors "k8s.io/apimachinery/pkg/api/errors" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 29 "k8s.io/apimachinery/pkg/util/wait" 30 ) 31 32 func (ctx *TestCtx) GetNamespace() (string, error) { 33 if ctx.namespace != "" { 34 return ctx.namespace, nil 35 } 36 if *singleNamespace { 37 ctx.namespace = Global.Namespace 38 return ctx.namespace, nil 39 } 40 // create namespace 41 ctx.namespace = ctx.GetID() 42 namespaceObj := &core.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ctx.namespace}} 43 _, err := Global.KubeClient.CoreV1().Namespaces().Create(namespaceObj) 44 if apierrors.IsAlreadyExists(err) { 45 return "", fmt.Errorf("namespace %s already exists: %v", ctx.namespace, err) 46 } else if err != nil { 47 return "", err 48 } 49 ctx.AddCleanupFn(func() error { 50 return Global.KubeClient.CoreV1().Namespaces().Delete(ctx.namespace, metav1.NewDeleteOptions(0)) 51 }) 52 return ctx.namespace, nil 53 } 54 55 func (ctx *TestCtx) createFromYAML(yamlFile []byte, skipIfExists bool, cleanupOptions *CleanupOptions) error { 56 namespace, err := ctx.GetNamespace() 57 if err != nil { 58 return err 59 } 60 scanner := yamlutil.NewYAMLScanner(yamlFile) 61 for scanner.Scan() { 62 yamlSpec := scanner.Bytes() 63 64 obj := &unstructured.Unstructured{} 65 jsonSpec, err := yaml.YAMLToJSON(yamlSpec) 66 if err != nil { 67 return fmt.Errorf("could not convert yaml file to json: %v", err) 68 } 69 if err := obj.UnmarshalJSON(jsonSpec); err != nil { 70 return fmt.Errorf("failed to unmarshal object spec: (%v)", err) 71 } 72 obj.SetNamespace(namespace) 73 err = Global.Client.Create(goctx.TODO(), obj, cleanupOptions) 74 if skipIfExists && apierrors.IsAlreadyExists(err) { 75 continue 76 } 77 if err != nil { 78 _, restErr := restMapper.RESTMappings(obj.GetObjectKind().GroupVersionKind().GroupKind()) 79 if restErr == nil { 80 return err 81 } 82 // don't store error, as only error will be timeout. Error from runtime client will be easier for 83 // the user to understand than the timeout error, so just use that if we fail 84 _ = wait.PollImmediate(time.Second*1, time.Second*10, func() (bool, error) { 85 restMapper.Reset() 86 _, err := restMapper.RESTMappings(obj.GetObjectKind().GroupVersionKind().GroupKind()) 87 if err != nil { 88 return false, nil 89 } 90 return true, nil 91 }) 92 err = Global.Client.Create(goctx.TODO(), obj, cleanupOptions) 93 if skipIfExists && apierrors.IsAlreadyExists(err) { 94 continue 95 } 96 if err != nil { 97 return err 98 } 99 } 100 } 101 102 if err := scanner.Err(); err != nil { 103 return fmt.Errorf("failed to scan manifest: (%v)", err) 104 } 105 return nil 106 } 107 108 func (ctx *TestCtx) InitializeClusterResources(cleanupOptions *CleanupOptions) error { 109 // create namespaced resources 110 namespacedYAML, err := ioutil.ReadFile(*Global.NamespacedManPath) 111 if err != nil { 112 return fmt.Errorf("failed to read namespaced manifest: %v", err) 113 } 114 return ctx.createFromYAML(namespacedYAML, false, cleanupOptions) 115 }