github.com/zntrio/harp/v2@v2.0.9/pkg/bundle/template/visitor/secretbuilder/application.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package secretbuilder
    19  
    20  import (
    21  	"fmt"
    22  	"strings"
    23  
    24  	bundlev1 "github.com/zntrio/harp/v2/api/gen/go/harp/bundle/v1"
    25  	"github.com/zntrio/harp/v2/pkg/bundle/template/visitor"
    26  	csov1 "github.com/zntrio/harp/v2/pkg/cso/v1"
    27  	"github.com/zntrio/harp/v2/pkg/template/engine"
    28  )
    29  
    30  type applicationSecretBuilder struct {
    31  	results         chan *bundlev1.Package
    32  	templateContext engine.Context
    33  
    34  	// Context
    35  	quality   string
    36  	platform  string
    37  	product   string
    38  	version   string
    39  	component string
    40  	err       error
    41  }
    42  
    43  // -----------------------------------------------------------------------------
    44  
    45  // Infrastructure returns a visitor instance to generate secretpath
    46  // and values.
    47  func application(results chan *bundlev1.Package, templateContext engine.Context, quality, platform, product, version string) (visitor.ApplicationVisitor, error) {
    48  	// Parse selector values
    49  	platformQuality, err := engine.RenderContext(templateContext, quality)
    50  	if err != nil {
    51  		return nil, fmt.Errorf("unable to render platform.quality: %w", err)
    52  	}
    53  	if strings.TrimSpace(platformQuality) == "" {
    54  		return nil, fmt.Errorf("quality selector must not be empty")
    55  	}
    56  
    57  	platformName, err := engine.RenderContext(templateContext, platform)
    58  	if err != nil {
    59  		return nil, fmt.Errorf("unable to render platform.name: %w", err)
    60  	}
    61  	if strings.TrimSpace(platformName) == "" {
    62  		return nil, fmt.Errorf("platform selector must not be empty")
    63  	}
    64  
    65  	productName, err := engine.RenderContext(templateContext, product)
    66  	if err != nil {
    67  		return nil, fmt.Errorf("unable to render product.name: %w", err)
    68  	}
    69  	if strings.TrimSpace(productName) == "" {
    70  		return nil, fmt.Errorf("product selector must not be empty")
    71  	}
    72  
    73  	productVersion, err := engine.RenderContext(templateContext, version)
    74  	if err != nil {
    75  		return nil, fmt.Errorf("unable to render product.version: %w", err)
    76  	}
    77  	if strings.TrimSpace(productVersion) == "" {
    78  		return nil, fmt.Errorf("version selector must not be empty")
    79  	}
    80  
    81  	return &applicationSecretBuilder{
    82  		results:         results,
    83  		templateContext: templateContext,
    84  		quality:         platformQuality,
    85  		platform:        platformName,
    86  		product:         productName,
    87  		version:         productVersion,
    88  	}, nil
    89  }
    90  
    91  // -----------------------------------------------------------------------------
    92  
    93  func (b *applicationSecretBuilder) Error() error {
    94  	return b.err
    95  }
    96  
    97  func (b *applicationSecretBuilder) VisitForComponent(obj *bundlev1.ApplicationComponentNS) {
    98  	// Check arguments
    99  	if obj == nil {
   100  		return
   101  	}
   102  
   103  	// Set context values
   104  	b.component, b.err = engine.RenderContext(b.templateContext, obj.Name)
   105  	if b.err != nil {
   106  		return
   107  	}
   108  
   109  	for _, item := range obj.Secrets {
   110  		// Check arguments
   111  		if item == nil {
   112  			continue
   113  		}
   114  
   115  		// Parse suffix with template engine
   116  		suffix, err := engine.RenderContext(b.templateContext, item.Suffix)
   117  		if err != nil {
   118  			b.err = fmt.Errorf("unable to merge template is suffix %q", item.Suffix)
   119  			return
   120  		}
   121  
   122  		// Generate secret suffix
   123  		secretPath, err := csov1.RingApplication.Path(b.quality, b.platform, b.product, b.version, b.component, suffix)
   124  		if err != nil {
   125  			b.err = err
   126  			return
   127  		}
   128  
   129  		// Prepare template model
   130  		tmplModel := &struct {
   131  			Quality   string
   132  			Platform  string
   133  			Product   string
   134  			Version   string
   135  			Component string
   136  			Secret    *bundlev1.SecretSuffix
   137  		}{
   138  			Quality:   b.quality,
   139  			Platform:  b.platform,
   140  			Product:   b.product,
   141  			Version:   b.version,
   142  			Component: b.component,
   143  			Secret:    item,
   144  		}
   145  
   146  		// Compile template
   147  		p, err := parseSecretTemplate(b.templateContext, secretPath, item, tmplModel)
   148  		if err != nil {
   149  			b.err = err
   150  			return
   151  		}
   152  
   153  		// Add package to collection
   154  		b.results <- p
   155  	}
   156  }