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

     1  // Copyright (c) 2021, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package ddl
     6  
     7  import (
     8  	"encoding/json"
     9  	"fmt"
    10  	"os"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/choria-io/go-choria/providers/agent/mcorpc/ddl/common"
    15  )
    16  
    17  // Metadata describes an agent at a high level and is required for any agent
    18  type Metadata struct {
    19  	License     string `json:"license"`
    20  	Author      string `json:"author"`
    21  	Timeout     int    `json:"timeout"`
    22  	Name        string `json:"name"`
    23  	Version     string `json:"version"`
    24  	URL         string `json:"url"`
    25  	Description string `json:"description"`
    26  	Provider    string `json:"provider,omitempty"`
    27  }
    28  
    29  type DDL struct {
    30  	Schema   string                        `json:"$schema"`
    31  	Metadata Metadata                      `json:"metadata"`
    32  	Query    *common.InputItem             `json:"query"`
    33  	Output   map[string]*common.OutputItem `json:"output"`
    34  
    35  	SourceLocation string `json:"-"`
    36  
    37  	sync.Mutex
    38  }
    39  
    40  // New creates a new DDL from a JSON file
    41  func New(file string) (*DDL, error) {
    42  	ddl := &DDL{
    43  		SourceLocation: file,
    44  	}
    45  
    46  	dat, err := os.ReadFile(file)
    47  	if err != nil {
    48  		return nil, fmt.Errorf("could not load DDL data: %s", err)
    49  	}
    50  
    51  	err = json.Unmarshal(dat, ddl)
    52  	if err != nil {
    53  		return nil, fmt.Errorf("could not parse JSON data in %s: %s", file, err)
    54  	}
    55  
    56  	return ddl, nil
    57  }
    58  
    59  func Find(plugin string, libdirs []string) (ddl *DDL, err error) {
    60  	EachFile(libdirs, func(n string, f string) bool {
    61  		if n == plugin {
    62  			ddl, err = New(f)
    63  			return true
    64  		}
    65  
    66  		return false
    67  	})
    68  
    69  	if err != nil {
    70  		return nil, fmt.Errorf("could not load data plugin %s: %s", plugin, err)
    71  	}
    72  
    73  	if ddl == nil {
    74  		return nil, fmt.Errorf("could not find DDL file for %s", plugin)
    75  	}
    76  
    77  	return ddl, nil
    78  }
    79  
    80  // EachFile calls cb with a path to every found data DDL, stops looking when br is true
    81  func EachFile(libdirs []string, cb func(name string, path string) (br bool)) {
    82  	common.EachFile("data", libdirs, cb)
    83  }
    84  
    85  // Timeout is the timeout for this data plugin
    86  func (d *DDL) Timeout() time.Duration {
    87  	if d.Metadata.Timeout == 0 {
    88  		return 10 * time.Second
    89  	}
    90  
    91  	return time.Second * time.Duration(d.Metadata.Timeout)
    92  }