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

     1  package kube
     2  
     3  import (
     4  	"encoding/base64"
     5  	"github.com/Masterminds/goutils"
     6  	k8serr "k8s.io/apimachinery/pkg/api/errors"
     7  	"sigs.k8s.io/kustomize/kyaml/yaml"
     8  	"strings"
     9  )
    10  
    11  type LabelFilter struct {
    12  	Labels map[string]string
    13  }
    14  
    15  func (l LabelFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
    16  	filters := make([]yaml.Filter, 0)
    17  	for k, v := range l.Labels {
    18  		filters = append(filters, yaml.SetLabel(k, v))
    19  	}
    20  	for _, node := range nodes {
    21  		if _, err := node.Pipe(filters...); err != nil {
    22  			return nil, err
    23  		}
    24  	}
    25  	return nodes, nil
    26  }
    27  
    28  type ContainerVersionFilter struct {
    29  	Version string
    30  }
    31  
    32  func (cv ContainerVersionFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
    33  	for _, node := range nodes {
    34  		containers, err := node.Pipe(yaml.Lookup("spec", "template", "spec", "containers"))
    35  		if err != nil || containers == nil {
    36  			continue
    37  		}
    38  
    39  		// Set ModelaSystem release
    40  		_ = node.PipeE(yaml.Lookup("spec", "release"), yaml.Set(yaml.NewStringRNode(cv.Version)))
    41  
    42  		// Visit each container and apply the container version
    43  		_ = containers.VisitElements(func(node *yaml.RNode) error {
    44  			imageNode, _ := node.Pipe(yaml.Lookup("image"))
    45  			image, _ := imageNode.String()
    46  			image = strings.Replace(image, "\n", "", -1)
    47  			// Skip data-dock image; this container is to be deprecated in a future release
    48  			if strings.Contains(image, "ghcr.io/metaprov/modela-data-dock") {
    49  				return nil
    50  			}
    51  
    52  			image = strings.Split(image, ":")[0] + ":" + cv.Version
    53  			_ = node.PipeE(
    54  				yaml.Lookup("image"),
    55  				yaml.Set(yaml.NewStringRNode(image)))
    56  
    57  			return nil
    58  		})
    59  	}
    60  
    61  	return nodes, nil
    62  }
    63  
    64  type NamespaceFilter struct {
    65  	Namespace string
    66  }
    67  
    68  func (nf NamespaceFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
    69  	for _, node := range nodes {
    70  		_ = node.SetNamespace(nf.Namespace)
    71  		_ = node.PipeE(yaml.Lookup("spec", "tenantRef", "name"), yaml.Set(yaml.NewStringRNode(nf.Namespace)))
    72  		_ = node.PipeE(yaml.Lookup("spec", "secretRef", "namespace"), yaml.Set(yaml.NewStringRNode(nf.Namespace)))
    73  	}
    74  
    75  	return nodes, nil
    76  }
    77  
    78  type TenantFilter struct {
    79  	TenantName string
    80  }
    81  
    82  func (t TenantFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
    83  	for _, node := range nodes {
    84  		switch node.GetKind() {
    85  		case "DataProduct":
    86  			if err := node.PipeE(
    87  				yaml.Lookup("spec", "defaultLabName"),
    88  				yaml.Set(yaml.NewStringRNode(t.TenantName+"-lab"))); err != nil {
    89  				return nil, err
    90  			}
    91  
    92  			if err := node.PipeE(
    93  				yaml.Lookup("spec", "defaultServingSiteName"),
    94  				yaml.Set(yaml.NewStringRNode(t.TenantName+"-serving-site"))); err != nil {
    95  				return nil, err
    96  			}
    97  		case "Lab":
    98  			if err := node.SetName(t.TenantName + "-lab"); err != nil {
    99  				return nil, err
   100  			}
   101  		case "ServingSite":
   102  			if err := node.SetName(t.TenantName + "-serving-site"); err != nil {
   103  				return nil, err
   104  			}
   105  		case "Tenant":
   106  			if err := node.SetName(t.TenantName); err != nil {
   107  				return nil, err
   108  			}
   109  			if err := node.SetNamespace("modela-system"); err != nil {
   110  				return nil, err
   111  			}
   112  
   113  			if err := node.PipeE(
   114  				yaml.Lookup("spec", "defaultLabName"),
   115  				yaml.Set(yaml.NewStringRNode(t.TenantName+"-lab"))); err != nil {
   116  				return nil, err
   117  			}
   118  
   119  			if err := node.PipeE(
   120  				yaml.Lookup("spec", "defaultServingSiteName"),
   121  				yaml.Set(yaml.NewStringRNode(t.TenantName+"-serving-site"))); err != nil {
   122  				return nil, err
   123  			}
   124  
   125  		}
   126  	}
   127  	return nodes, nil
   128  }
   129  
   130  type ManagedImageFilter struct {
   131  	Version string
   132  }
   133  
   134  func (mi ManagedImageFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
   135  	for _, node := range nodes {
   136  		if node.GetKind() == "ManagedImage" {
   137  			_ = node.PipeE(yaml.Lookup("spec", "tag"), yaml.Set(yaml.NewStringRNode(mi.Version)))
   138  		}
   139  	}
   140  	return nodes, nil
   141  }
   142  
   143  type JwtSecretFilter struct{}
   144  
   145  func (j JwtSecretFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
   146  	for _, node := range nodes {
   147  		if node.GetName() == "modela-auth-token" {
   148  			str, _ := goutils.RandomAlphaNumeric(32)
   149  			b64 := base64.StdEncoding.EncodeToString([]byte(str))
   150  			_ = node.PipeE(yaml.Lookup("data", "jwt-secret"), yaml.Set(yaml.NewStringRNode(b64)))
   151  		}
   152  	}
   153  	return nodes, nil
   154  }
   155  
   156  type RedisSecretFilter struct {
   157  	Password string
   158  }
   159  
   160  func (r RedisSecretFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
   161  	for _, node := range nodes {
   162  		if node.GetName() == "redis-secret" {
   163  			_ = node.PipeE(
   164  				yaml.Lookup("data", "redis-password"),
   165  				yaml.Set(yaml.NewStringRNode(base64.StdEncoding.EncodeToString([]byte(r.Password)))),
   166  			)
   167  		}
   168  	}
   169  
   170  	return nodes, nil
   171  }
   172  
   173  type ModelaConfigFilter struct {
   174  	VaultAddress   string
   175  	VaultMountPath string
   176  }
   177  
   178  func (m ModelaConfigFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
   179  	for _, node := range nodes {
   180  		if node.GetName() == "modela-config" {
   181  			_ = node.PipeE(
   182  				yaml.Lookup("spec", "vaultAddress"),
   183  				yaml.Set(yaml.NewStringRNode(m.VaultAddress)),
   184  			)
   185  			_ = node.PipeE(
   186  				yaml.Lookup("spec", "vaultMountPath"),
   187  				yaml.Set(yaml.NewStringRNode(m.VaultMountPath)),
   188  			)
   189  		}
   190  	}
   191  
   192  	return nodes, nil
   193  }
   194  
   195  type OwnerReferenceFilter struct {
   196  	Owner          string
   197  	OwnerNamespace string
   198  	UID            string
   199  }
   200  
   201  func (o OwnerReferenceFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
   202  	for _, node := range nodes {
   203  		if o.OwnerNamespace != node.GetNamespace() {
   204  			continue
   205  		}
   206  		ownerReference := yaml.NewMapRNode(&map[string]string{
   207  			"apiVersion":         "management.modela.ai/v1alpha1",
   208  			"kind":               "Modela",
   209  			"name":               o.Owner,
   210  			"uid":                o.UID,
   211  			"blockOwnerDeletion": "true",
   212  			"controller":         "true",
   213  		})
   214  		_ = node.PipeE(yaml.LookupCreate(yaml.SequenceNode, "metadata", "ownerReferences"),
   215  			yaml.Append(ownerReference.YNode()))
   216  	}
   217  	return nodes, nil
   218  }
   219  
   220  type SkipCertManagerFilter struct{}
   221  
   222  func (o SkipCertManagerFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
   223  	var outNodes []*yaml.RNode
   224  	_, err := GetCRDVersion("issuers.cert-manager.io")
   225  	var certManagerMissing = k8serr.IsNotFound(err)
   226  	for _, node := range nodes {
   227  		if certManagerMissing && node.GetApiVersion() == "cert-manager.io/v1" {
   228  			continue
   229  		}
   230  		outNodes = append(outNodes, node)
   231  	}
   232  
   233  	return outNodes, nil
   234  }
   235  
   236  type ConnectionFilter struct {
   237  	PgvectorEnabled bool
   238  	MongoEnabled    bool
   239  }
   240  
   241  func (cf ConnectionFilter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
   242  	var outNodes []*yaml.RNode
   243  	for _, node := range nodes {
   244  		if node.GetName() == "postgres-vector-connection" && !cf.PgvectorEnabled {
   245  			continue
   246  		}
   247  		if node.GetName() == "mongodb-connection" && !cf.MongoEnabled {
   248  			continue
   249  		}
   250  		outNodes = append(outNodes, node)
   251  	}
   252  
   253  	return outNodes, nil
   254  }