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  }