github.com/octohelm/wagon@v0.0.0-20240308040401-88662650dc0b/pkg/engine/plan/internal/task.go (about)

     1  package internal
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"reflect"
     8  
     9  	cueformat "cuelang.org/go/cue/format"
    10  	"github.com/octohelm/wagon/pkg/engine/plan"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  type FlowTask interface {
    15  	flowTask()
    16  }
    17  
    18  type Task struct {
    19  }
    20  
    21  func (Task) flowTask() {
    22  
    23  }
    24  
    25  func taskFrom(r TaskRegister, t any) *task {
    26  	tpe := reflect.TypeOf(t)
    27  	if tpe.Kind() == reflect.Ptr {
    28  		tpe = tpe.Elem()
    29  	}
    30  
    31  	c := newConvert(r)
    32  
    33  	pt := &task{
    34  		tpe:          tpe,
    35  		outputFields: map[string]int{},
    36  		cueType:      c.toCueType(tpe, opt{naming: tpe.Name()}),
    37  	}
    38  
    39  	if _, ok := t.(FlowTask); ok {
    40  		pt.flowTask = true
    41  	}
    42  
    43  	walkFields(tpe, func(info *fieldInfo) {
    44  		for _, attr := range info.attrs {
    45  			if attr == "generated" {
    46  				pt.outputFields[info.name] = info.idx
    47  			}
    48  		}
    49  	})
    50  
    51  	return pt
    52  }
    53  
    54  type task struct {
    55  	tpe          reflect.Type
    56  	outputFields map[string]int
    57  	flowTask     bool
    58  	cueType      []byte
    59  }
    60  
    61  func (t *task) Name() string {
    62  	return t.tpe.Name()
    63  }
    64  
    65  func (t *task) New(planTask plan.Task) (plan.TaskRunner, error) {
    66  	r := &taskRunner{
    67  		task:            planTask,
    68  		inputTaskRunner: reflect.New(t.tpe),
    69  		outputFields:    map[string]int{},
    70  	}
    71  
    72  	for f, i := range t.outputFields {
    73  		r.outputFields[f] = i
    74  	}
    75  
    76  	return r, nil
    77  }
    78  
    79  func (t *task) WriteCueDeclTo(w io.Writer) error {
    80  	b := bytes.NewBuffer(nil)
    81  	name := t.Name()
    82  
    83  	if t.flowTask {
    84  		_, _ = fmt.Fprintf(b, `#%s: $wagon: task: name: %q
    85  `, name, name)
    86  	}
    87  
    88  	_, _ = fmt.Fprintf(b, `#%s: %s
    89  `, name, t.cueType)
    90  
    91  	data, err := cueformat.Source(b.Bytes(), cueformat.Simplify())
    92  	if err != nil {
    93  		return errors.Wrapf(err, `format invalid: %s`, b.Bytes())
    94  	}
    95  	_, err = w.Write(data)
    96  	return err
    97  }