github.com/metaprov/modela-operator@v0.0.0-20240118193048-f378be8b74d2/pkg/kube/resource.go (about)

     1  package kube
     2  
     3  import (
     4  	"context"
     5  	"io/ioutil"
     6  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
     7  	"k8s.io/apimachinery/pkg/runtime/schema"
     8  	"k8s.io/apimachinery/pkg/util/sets"
     9  	"k8s.io/cli-runtime/pkg/genericclioptions"
    10  	"k8s.io/cli-runtime/pkg/printers"
    11  	"k8s.io/cli-runtime/pkg/resource"
    12  
    13  	"k8s.io/kubectl/pkg/cmd/apply"
    14  	k8sdelete "k8s.io/kubectl/pkg/cmd/delete"
    15  	"k8s.io/kubectl/pkg/cmd/util"
    16  	"k8s.io/kubectl/pkg/scheme"
    17  	"log"
    18  	"path/filepath"
    19  	ctrl "sigs.k8s.io/controller-runtime"
    20  	"sigs.k8s.io/controller-runtime/pkg/client"
    21  	"sigs.k8s.io/controller-runtime/pkg/client/config"
    22  	"sigs.k8s.io/kustomize/api/krusty"
    23  	"sigs.k8s.io/kustomize/kyaml/filesys"
    24  	"sigs.k8s.io/kustomize/kyaml/kio"
    25  	"strings"
    26  )
    27  
    28  var kustomizer = krusty.MakeKustomizer(krusty.MakeDefaultOptions())
    29  
    30  func LoadResources(folder string, filters []kio.Filter, loadAll bool) ([]byte, int, error) {
    31  	path, _ := filepath.Abs("./manifests")
    32  	resMap, err := kustomizer.Run(filesys.MakeFsOnDisk(), filepath.Join(path, folder))
    33  	if err != nil {
    34  		return nil, 0, err
    35  	}
    36  	for _, filter := range filters {
    37  		if err = resMap.ApplyFilter(filter); err != nil {
    38  			return nil, 0, err
    39  		}
    40  	}
    41  
    42  	var missing = 0
    43  	k8sclient, err := client.New(config.GetConfigOrDie(), client.Options{})
    44  
    45  	if !loadAll {
    46  		for _, res := range resMap.Resources() {
    47  			obj := &unstructured.Unstructured{}
    48  			obj.SetGroupVersionKind(schema.GroupVersionKind{
    49  				Group:   res.GetGvk().Group,
    50  				Version: res.GetGvk().Version,
    51  				Kind:    res.GetGvk().Kind,
    52  			})
    53  			err := k8sclient.Get(context.Background(), client.ObjectKey{Namespace: res.GetNamespace(), Name: res.GetName()}, obj)
    54  			if err != nil {
    55  				missing++
    56  			} else {
    57  				_ = resMap.Remove(res.OrgId())
    58  			}
    59  		}
    60  	}
    61  
    62  	if yaml, err := resMap.AsYaml(); err == nil {
    63  		return yaml, missing, nil
    64  	} else {
    65  		return nil, missing, err
    66  	}
    67  }
    68  
    69  func ApplyYaml(yaml string) error {
    70  	f := util.NewFactory(RESTClientGetter{RestConfig: ctrl.GetConfigOrDie()})
    71  	mapper, err := f.ToRESTMapper()
    72  	if err != nil {
    73  		return err
    74  	}
    75  	dynamicClient, err := f.DynamicClient()
    76  	if err != nil {
    77  		return err
    78  	}
    79  	openAPISchema, _ := f.OpenAPISchema()
    80  
    81  	tmpfile, _ := ioutil.TempFile("", "*kubectl_manifest.yaml")
    82  	_, _ = tmpfile.Write([]byte(yaml))
    83  	_ = tmpfile.Close()
    84  
    85  	applyOptions := &apply.ApplyOptions{
    86  		IOStreams: genericclioptions.IOStreams{
    87  			In:     strings.NewReader(yaml),
    88  			Out:    log.Writer(),
    89  			ErrOut: log.Writer(),
    90  		},
    91  		Builder:       f.NewBuilder(),
    92  		DynamicClient: dynamicClient,
    93  		Mapper:        mapper,
    94  		OpenAPISchema: openAPISchema,
    95  		Recorder:      genericclioptions.NoopRecorder{},
    96  		ToPrinter: func(string) (printers.ResourcePrinter, error) {
    97  			return &printers.NamePrinter{Operation: "serverside-applied"}, nil
    98  		},
    99  		DeleteOptions: &k8sdelete.DeleteOptions{
   100  			FilenameOptions: resource.FilenameOptions{
   101  				Filenames: []string{tmpfile.Name()},
   102  			},
   103  		},
   104  		EnforceNamespace: false,
   105  
   106  		VisitedUids:       sets.NewString(),
   107  		VisitedNamespaces: sets.NewString(),
   108  		PrintFlags:        genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
   109  		Overwrite:         true,
   110  		ServerSideApply:   true,
   111  		FieldManager:      "kubectl",
   112  		ForceConflicts:    true,
   113  	}
   114  
   115  	err = applyOptions.Run()
   116  	if err != nil {
   117  		return err
   118  	}
   119  
   120  	return nil
   121  
   122  }
   123  
   124  func ApplyUrlKustomize(url string) error {
   125  	f := util.NewFactory(RESTClientGetter{RestConfig: ctrl.GetConfigOrDie()})
   126  	mapper, err := f.ToRESTMapper()
   127  	if err != nil {
   128  		return err
   129  	}
   130  	dynamicClient, err := f.DynamicClient()
   131  	if err != nil {
   132  		return err
   133  	}
   134  	openAPISchema, _ := f.OpenAPISchema()
   135  	applyOptions := &apply.ApplyOptions{
   136  		IOStreams: genericclioptions.IOStreams{
   137  			Out:    log.Writer(),
   138  			ErrOut: log.Writer(),
   139  		},
   140  		Builder:       f.NewBuilder(),
   141  		DynamicClient: dynamicClient,
   142  		Mapper:        mapper,
   143  		OpenAPISchema: openAPISchema,
   144  		Recorder:      genericclioptions.NoopRecorder{},
   145  		ToPrinter: func(string) (printers.ResourcePrinter, error) {
   146  			return &printers.NamePrinter{Operation: "serverside-applied"}, nil
   147  		},
   148  		DeleteOptions: &k8sdelete.DeleteOptions{
   149  			FilenameOptions: resource.FilenameOptions{
   150  				Kustomize: url,
   151  			},
   152  		},
   153  		EnforceNamespace: false,
   154  
   155  		VisitedUids:       sets.NewString(),
   156  		VisitedNamespaces: sets.NewString(),
   157  		PrintFlags:        genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
   158  		Overwrite:         true,
   159  		ServerSideApply:   true,
   160  		FieldManager:      "kubectl",
   161  	}
   162  
   163  	err = applyOptions.Run()
   164  	if err != nil {
   165  		return err
   166  	}
   167  
   168  	return nil
   169  }