github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/providers/ddlresolver/filesystem_resolver.go (about)

     1  // Copyright (c) 2021-2022, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package ddlresolver
     6  
     7  import (
     8  	"context"
     9  	"encoding/json"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  	"sort"
    14  	"strings"
    15  
    16  	"github.com/choria-io/go-choria/inter"
    17  )
    18  
    19  // FileSystemDDLResolver resolves DDL in the lib directories configured in the framework
    20  type FileSystemDDLResolver struct{}
    21  
    22  func (f *FileSystemDDLResolver) String() string {
    23  	return "File System DDL Resolver"
    24  }
    25  
    26  func (f *FileSystemDDLResolver) DDL(ctx context.Context, kind string, name string, target any, fw inter.Framework) error {
    27  	b, err := f.DDLBytes(ctx, kind, name, fw)
    28  	if err != nil {
    29  		return err
    30  	}
    31  
    32  	return json.Unmarshal(b, target)
    33  }
    34  
    35  func (f *FileSystemDDLResolver) DDLBytes(_ context.Context, kind string, name string, fw inter.Framework) ([]byte, error) {
    36  	if kind != "agent" && kind != "data" {
    37  		return nil, fmt.Errorf("unsupported ddl type %q", kind)
    38  	}
    39  
    40  	var (
    41  		b   []byte
    42  		err error
    43  	)
    44  
    45  	f.EachFile(kind, f.libDirs(fw), func(n, p string) bool {
    46  		if n == name {
    47  			b, err = os.ReadFile(p)
    48  			return true
    49  		}
    50  		return false
    51  	})
    52  	if err != nil {
    53  		return nil, fmt.Errorf("could not find DDL %s/%s: %s", kind, name, err)
    54  	}
    55  	if len(b) == 0 {
    56  		return nil, fmt.Errorf("could not find DDL %s/%s", kind, name)
    57  	}
    58  
    59  	return b, nil
    60  }
    61  
    62  func (f *FileSystemDDLResolver) DDLNames(_ context.Context, kind string, fw inter.Framework) ([]string, error) {
    63  	if kind != "agent" && kind != "data" {
    64  		return nil, fmt.Errorf("unsupported ddl type %q", kind)
    65  	}
    66  
    67  	names := []string{}
    68  	f.EachFile(kind, f.libDirs(fw), func(n, _ string) bool {
    69  		names = append(names, n)
    70  		return false
    71  	})
    72  
    73  	sort.Strings(names)
    74  
    75  	return names, nil
    76  }
    77  
    78  func (f *FileSystemDDLResolver) libDirs(fw inter.Framework) []string {
    79  	return append(fw.Configuration().LibDir, fw.Configuration().Choria.RubyLibdir...)
    80  }
    81  
    82  func (f *FileSystemDDLResolver) EachFile(kind string, libdirs []string, cb func(name string, path string) (br bool)) {
    83  	for _, dir := range libdirs {
    84  		for _, n := range []string{"choria", "mcollective"} {
    85  			filepath.Walk(filepath.Join(dir, n, kind), func(path string, info os.FileInfo, err error) error {
    86  				if err != nil {
    87  					return err
    88  				}
    89  
    90  				if info.IsDir() {
    91  					return nil
    92  				}
    93  
    94  				_, name := filepath.Split(path)
    95  				extension := filepath.Ext(name)
    96  
    97  				if extension != ".json" {
    98  					return nil
    99  				}
   100  
   101  				cb(strings.TrimSuffix(name, extension), path)
   102  
   103  				return nil
   104  			})
   105  		}
   106  	}
   107  }