Skip to content

Commit

Permalink
Add OutputRegistry interface
Browse files Browse the repository at this point in the history
  • Loading branch information
jwillp committed Aug 21, 2024
1 parent 7dae1a0 commit 10d7b7a
Show file tree
Hide file tree
Showing 10 changed files with 833 additions and 182 deletions.
8 changes: 4 additions & 4 deletions hcl.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (l HCLGenericSpecLoader) Load(s Source) ([]Specification, error) {
return nil, errors.NewWithMessage(
UnsupportedSourceErrorCode,
fmt.Sprintf(
"invalid specification source \"%s\", unsupported format \"%s\"",
"invalid specification source %q, unsupported format %q",
s.Location,
s.Format,
),
Expand All @@ -63,7 +63,7 @@ func (l HCLGenericSpecLoader) Load(s Source) ([]Specification, error) {
return nil, errors.NewWithMessage(
InvalidHCLErrorCode,
fmt.Sprintf(
"invalid specification source \"%s\" at line %d:%d, block \"%s\" should contain a name",
"invalid specification source %q at line %d:%d, block %q should contain a name",
s.Location,
block.Range().Start.Line,
block.Range().Start.Column,
Expand All @@ -79,7 +79,7 @@ func (l HCLGenericSpecLoader) Load(s Source) ([]Specification, error) {
err,
InvalidHCLErrorCode,
fmt.Sprintf(
"invalid specification source \"%s\" at line %d:%d for block \"%s\"",
"invalid specification source %q at line %d:%d for block %q",
s.Location,
block.Range().Start.Line,
block.Range().Start.Column,
Expand Down Expand Up @@ -190,7 +190,7 @@ func (l HCLSpecLoader) Load(s Source) ([]Specification, error) {
return nil, errors.NewWithMessage(
UnsupportedSourceErrorCode,
fmt.Sprintf(
"invalid specification source \"%s\", unsupported format \"%s\"",
"invalid specification source %q, unsupported format %q",
s.Location,
s.Format,
),
Expand Down
56 changes: 56 additions & 0 deletions mkdiroutproc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package specter

import (
"fmt"
"github.com/morebec/go-errors/errors"
"os"
)

type DirectoryOutput struct {
Path string
Mode os.FileMode
}

type WriteDirectoryOutputsProcessorConfig struct {
// Add any configuration specific to directory processing if needed
UseRegistry bool
}

type WriteDirectoryOutputsProcessor struct {
config WriteDirectoryOutputsProcessorConfig
}

func NewWriteDirectoryOutputsProcessor(conf WriteDirectoryOutputsProcessorConfig) *WriteDirectoryOutputsProcessor {
return &WriteDirectoryOutputsProcessor{
config: conf,
}
}

func (p WriteDirectoryOutputsProcessor) Name() string {
return "directory_outputs_processor"
}

func (p WriteDirectoryOutputsProcessor) Process(ctx OutputProcessingContext) error {
ctx.Logger.Info("Creating output directories ...")

var directories []DirectoryOutput
for _, o := range ctx.Outputs {
dir, ok := o.Value.(DirectoryOutput)
if !ok {
continue
}
directories = append(directories, dir)
}

for _, dir := range directories {
ctx.Logger.Info(fmt.Sprintf("Creating directory %s ...", dir.Path))
err := os.MkdirAll(dir.Path, dir.Mode)
if err != nil {
ctx.Logger.Error(fmt.Sprintf("failed creating directory at %s", dir.Path))
return errors.Wrap(err, "failed creating output directories")
}
}

ctx.Logger.Success("Output directories created successfully.")
return nil
}
108 changes: 108 additions & 0 deletions outputregistry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package specter

import (
"encoding/json"
"github.com/morebec/go-errors/errors"
"os"
"sync"
"time"
)

// JSONOutputRegistry allows tracking on the file system the files that were written by the last execution
// of the WriteFileOutputsProcessor to perform cleaning operations on next executions.
type JSONOutputRegistry struct {
GeneratedAt time.Time `json:"generatedAt"`
OutputMap map[string]*JSONOutputRegistryProcessor `json:"files"`
FilePath string
mu sync.RWMutex // Mutex to protect concurrent access
}

type JSONOutputRegistryProcessor struct {
Outputs []string `json:"files"`
}

// NewJSONOutputRegistry returns a new output file registry.
func NewJSONOutputRegistry(fileName string) *JSONOutputRegistry {
return &JSONOutputRegistry{
GeneratedAt: time.Now(),
OutputMap: nil,
FilePath: fileName,
}
}

func (r *JSONOutputRegistry) Load() error {
r.mu.Lock()
defer r.mu.Unlock()

bytes, err := os.ReadFile(r.FilePath)

if err != nil {
if os.IsNotExist(err) {
return nil
}
return errors.WrapWithMessage(err, errors.InternalErrorCode, "failed loading output file registry")
}
if err := json.Unmarshal(bytes, r); err != nil {
return errors.WrapWithMessage(err, errors.InternalErrorCode, "failed loading output file registry")
}

return nil
}

func (r *JSONOutputRegistry) Save() error {
r.mu.RLock()
defer r.mu.RUnlock()

if r.OutputMap == nil {
return nil
}
// Generate a JSON file containing all output files for clean up later on
js, err := json.MarshalIndent(r, "", " ")
if err != nil {
return errors.Wrap(err, "failed generating output file registry")
}
if err := os.WriteFile(r.FilePath, js, os.ModePerm); err != nil {
return errors.Wrap(err, "failed generating output file registry")
}

return nil
}

func (r *JSONOutputRegistry) AddOutput(processorName string, outputName string) {
r.mu.Lock()
defer r.mu.Unlock()

if _, ok := r.OutputMap[processorName]; !ok {
r.OutputMap[processorName] = &JSONOutputRegistryProcessor{}
}
r.OutputMap[processorName].Outputs = append(r.OutputMap[processorName].Outputs, outputName)
}

func (r *JSONOutputRegistry) RemoveOutput(processorName string, outputName string) {
r.mu.Lock()
defer r.mu.Unlock()

if _, ok := r.OutputMap[processorName]; !ok {
return
}

var files []string
for _, file := range r.OutputMap[processorName].Outputs {
if file != outputName {
files = append(files, file)
}
}

r.OutputMap[processorName].Outputs = files
}

func (r *JSONOutputRegistry) Outputs(processorName string) []string {
r.mu.RLock()
defer r.mu.RUnlock()

outputs, ok := r.OutputMap[processorName]
if !ok {
return nil
}
return outputs.Outputs
}
Loading

0 comments on commit 10d7b7a

Please sign in to comment.