opencontrol/compliance-masonry

View on GitHub
pkg/cli/export/exportFormat.go

Summary

Maintainability
A
35 mins
Test Coverage
/*
 Copyright (C) 2018 OpenControl Contributors. See LICENSE.md for license.
*/

package export

import (
    "bufio"
    "bytes"
    "encoding/json"
    "errors"
    "fmt"
    "gopkg.in/yaml.v2"
    "io"
    "log"
    "os"
    "strings"

    "github.com/opencontrol/compliance-masonry/pkg/lib"
    "github.com/opencontrol/compliance-masonry/pkg/lib/common"
    "github.com/opencontrol/compliance-masonry/tools/certifications"
)

////////////////////////////////////////////////////////////////////////
// Package functions

// exportJSON - JSON output
func exportJSON(config *Config, workspace common.Workspace, output *exportOutput, writer io.Writer) []error {
    // result
    var errors []error

    // work vars
    var byteSlice []byte
    var err error

    // do the work
    byteSlice, err = json.Marshal(output)
    if err != nil {
        return returnErrors(err)
    }

    // flatten output?
    if config.Flatten {
        log.Println("JSON: Flatten")

        // decode json first
        mapped := map[string]interface{}{}
        err = json.Unmarshal(byteSlice, &mapped)
        if err != nil {
            return returnErrors(err)
        }

        // flatten the JSON (recursive)
        var flattened = make(map[string]interface{})
        var lkey string
        err := flatten(config, mapped, lkey, &flattened)
        if err != nil {
            return returnErrors(err)
        }
        var flattenedByteSlice []byte
        flattenedByteSlice, err = json.Marshal(flattened)
        if err != nil {
            return returnErrors(err)
        }
        writer.Write(flattenedByteSlice)
    } else {
        // direct output
        writer.Write(byteSlice)
    }

    return errors
}

// exportYAML - YAML output
func exportYAML(config *Config, workspace common.Workspace, output *exportOutput, writer io.Writer) []error {
    // result
    var dummyErrors []error

    // work vars
    var byteSlice []byte
    var err error

    // do the work
    byteSlice, err = yaml.Marshal(output)
    if err != nil {
        return returnErrors(err)
    }

    // flatten output?
    if config.Flatten {
        // we do not support flatten for YAML - returns 'map[interface {}]interface {}'
        return returnErrors(errors.New("--flatten unsupported for YAML"))
    }
    // direct output
    writer.Write(byteSlice)

    // just so we can return an empty array (not nil)
    return dummyErrors
}

// internal - handle export
func export(config *Config, workspace common.Workspace) []error {
    // sanity
    if len(strings.TrimSpace(config.DestinationFile)) == 0 {
        return returnErrors(errors.New("empty destination files"))
    }

    // create our work object
    var output exportOutput
    output.Config = config
    output.Data.Certification = workspace.GetCertification()
    output.Data.Components = workspace.GetAllComponents()
    output.Data.Standards = workspace.GetAllStandards()

    // handle output destination
    var writer io.Writer
    if config.DestinationFile == "-" {
        // send to stdout
        writer = os.Stdout
    } else if config.DestinationFile == "-str-" {
        // send to null buffer
        var b bytes.Buffer
        writer = bufio.NewWriter(&b)
    } else {
        // send to file
        file, err := os.Create(config.DestinationFile)
        if err != nil {
            return returnErrors(err)
        }
        writer = file
        defer file.Close()
    }

    // handle the output
    switch config.OutputFormat {
    case FormatJSON:
        return exportJSON(config, workspace, &output, writer)
    case FormatYAML:
        return exportYAML(config, workspace, &output, writer)
    default:
        return returnErrors(fmt.Errorf("unsupported OutputFormat '%s'", config.OutputFormat))
    }
}

// Export loads the inventory and writes output to destinaation
func Export(config Config) []error {
    // resolve the actual certification to use
    certificationPath, errs := certifications.GetCertification(config.OpencontrolDir, config.Certification)
    if errs != nil && len(errs) > 0 {
        return errs
    }

    // load all workspace data
    workspace, errs := lib.LoadData(config.OpencontrolDir, certificationPath)
    if errs != nil && len(errs) > 0 {
        return errs
    }

    // retrieve workspace data and write to output
    return export(&config, workspace)
}