github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/pkg/platform/runtime/executors/execmeta/execmeta.go (about)

     1  // Package execmeta models the executor meta data that is communicated from the
     2  // state tool to executors via file. The meta file is stored alongside the
     3  // executors and should be named "meta.as". It should be applied to the file
     4  // file system when the runtime is manifested on disk.
     5  //
     6  // IMPORTANT: This package should have minimal dependencies as it will be
     7  // imported by cmd/state-exec. The resulting compiled executable must remain as
     8  // small as possible.
     9  package execmeta
    10  
    11  import (
    12  	"bytes"
    13  	"encoding/json"
    14  	"fmt"
    15  	"io"
    16  	"os"
    17  	"path/filepath"
    18  	"strings"
    19  )
    20  
    21  type Target struct {
    22  	CommitUUID string
    23  	Namespace  string
    24  	Dir        string
    25  	Headless   bool
    26  }
    27  
    28  const (
    29  	MetaFileName           = "meta.as"
    30  	metaFileDetectionToken = `"SockPath":`
    31  )
    32  
    33  type ExecMeta struct {
    34  	SockPath   string
    35  	Env        []string
    36  	Bins       map[string]string // map[alias]dest
    37  	CommitUUID string
    38  	Namespace  string
    39  	Headless   bool
    40  }
    41  
    42  func New(sockPath string, env []string, t Target, bins map[string]string) *ExecMeta {
    43  	return &ExecMeta{
    44  		SockPath:   sockPath,
    45  		Env:        env,
    46  		Bins:       bins,
    47  		CommitUUID: t.CommitUUID,
    48  		Namespace:  t.Namespace,
    49  		Headless:   t.Headless,
    50  	}
    51  }
    52  
    53  func NewFromReader(r io.Reader) (*ExecMeta, error) {
    54  	m := ExecMeta{}
    55  	if err := json.NewDecoder(r).Decode(&m); err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	return &m, nil
    60  }
    61  
    62  // NewFromFile is a convenience func, not intended to be tested.
    63  func NewFromFile(path string) (*ExecMeta, error) {
    64  	data, err := readFile(path)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	buf := bytes.NewBuffer(data)
    69  	return NewFromReader(buf)
    70  }
    71  
    72  func (m *ExecMeta) Encode(w io.Writer) error {
    73  	return json.NewEncoder(w).Encode(m)
    74  }
    75  
    76  // WriteToDisk is a convenience func, not intended to be unit tested.
    77  func (m *ExecMeta) WriteToDisk(dir string) error {
    78  	path := filepath.Join(dir, MetaFileName)
    79  	buf := &bytes.Buffer{}
    80  	if err := m.Encode(buf); err != nil {
    81  		return err
    82  	}
    83  	if err := writeFile(path, buf.Bytes()); err != nil {
    84  		return err
    85  	}
    86  	return nil
    87  }
    88  
    89  func IsMetaFile(fileContents []byte) bool {
    90  	return strings.Contains(string(fileContents), metaFileDetectionToken)
    91  }
    92  
    93  func readFile(filePath string) ([]byte, error) {
    94  	b, err := os.ReadFile(filePath)
    95  	if err != nil {
    96  		return nil, fmt.Errorf("os.ReadFile %s failed: %w", filePath, err)
    97  	}
    98  	return b, nil
    99  }
   100  
   101  func writeFile(filePath string, data []byte) error {
   102  	f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
   103  	if err != nil {
   104  		return fmt.Errorf("os.OpenFile %s failed: %w", filePath, err)
   105  	}
   106  	defer f.Close()
   107  
   108  	_, err = f.Write(data)
   109  	if err != nil {
   110  		return fmt.Errorf("file.Write %s failed: %w", filePath, err)
   111  	}
   112  	return nil
   113  }