Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions internal/handlers/descriptors/gctrees.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
---
##############################################################################
# Reader Commands
##############################################################################
get:
use: gctrees
group: configuration-manager
Expand All @@ -15,9 +12,6 @@ describe:
description: |
Display details about a gctree

##############################################################################
# Writer Commands
##############################################################################
create:
use: gctree <name> <type>
group: configuration-manager
Expand All @@ -41,13 +35,9 @@ clear:
description: |
Delete all configured gctrees

##############################################################################
# Promoter Commands
##############################################################################
import:
use: gctree <path>
group: configuration-manager
disabled: true
description: |
Import a Golden Config tree

Expand Down
108 changes: 79 additions & 29 deletions internal/runners/gctrees.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"strings"

"github.com/itential/ipctl/internal/flags"
"github.com/itential/ipctl/internal/utils"
"github.com/itential/ipctl/pkg/client"
"github.com/itential/ipctl/pkg/config"
"github.com/itential/ipctl/pkg/logger"
Expand All @@ -29,6 +28,12 @@ func NewGoldenConfigRunner(client client.Client, cfg *config.Config) *GoldenConf
}
}

/*
******************************************************************************
Reader interface
******************************************************************************
*/

// Get implements the `get golden-config <name>` command
func (r *GoldenConfigRunner) Get(in Request) (*Response, error) {
logger.Trace()
Expand All @@ -53,6 +58,12 @@ func (r *GoldenConfigRunner) Describe(in Request) (*Response, error) {
return NotImplemented(in)
}

/*
******************************************************************************
Writer interface
******************************************************************************
*/

// Create implements the `create golden-config <name> <type>` command
func (r *GoldenConfigRunner) Create(in Request) (*Response, error) {
logger.Trace()
Expand Down Expand Up @@ -98,58 +109,97 @@ func (r *GoldenConfigRunner) Clear(in Request) (*Response, error) {
return NotImplemented(in)
}

func (r *GoldenConfigRunner) Copy(in Request) (*Response, error) {
return NotImplemented(in)
}
/*
******************************************************************************
Importer interface
******************************************************************************
*/

// Import implements the `import gctree ...` command
func (r *GoldenConfigRunner) Import(in Request) (*Response, error) {
return NotImplemented(in)
}

// Export is the implementation of the command `export golden-config <name>`
func (r *GoldenConfigRunner) Export(in Request) (*Response, error) {
logger.Trace()

var common flags.AssetExportCommon
utils.LoadObject(in.Common, &common)
common := in.Common.(*flags.AssetImportCommon)

if common.Path != "" {
utils.EnsurePathExists(common.Path)
}
var gctree services.GoldenConfigTree

name := in.Args[0]

trees, err := r.service.GetAll()
if err != nil {
if err := importUnmarshalFromRequest(in, &gctree); err != nil {
return nil, err
}

var id string
for _, ele := range trees {
if ele.Name == name {
id = ele.Id
}
if err := r.importTree(gctree, common.Replace); err != nil {
return nil, err
}

if id == "" {
return nil, errors.New(fmt.Sprintf("Unable to find tree with name %s", name))
return NewResponse(
fmt.Sprintf("Successfully imported gctree `%s`", gctree.Name),
WithObject(gctree),
), nil
}

/*
******************************************************************************
Exporter interface
******************************************************************************
*/

// Export implements the `export gctree ...` command
func (r *GoldenConfigRunner) Export(in Request) (*Response, error) {
logger.Trace()

name := in.Args[0]

gctree, err := r.service.GetByName(name)
if err != nil {
return nil, err
}

tree, err := r.service.Export(id)
res, err := r.service.Export(gctree.Id)
if err != nil {
return nil, err
}

fn := fmt.Sprintf("%s.gctree.json", name)
if err := utils.WriteJsonToDisk(tree, fn, common.Path); err != nil {
fn := fmt.Sprintf("%s.gctree.json", res.Name)

if err := exportAssetFromRequest(in, res, fn); err != nil {
return nil, err
}

return NewResponse(
fmt.Sprintf("Successfully exported golden config tree `%s`", tree.Name),
fmt.Sprintf("Successfully exported gctree `%s`", gctree.Name),
WithObject(gctree),
), nil
}

/*
*******************************************************************************
Private functions
*******************************************************************************
*/

func (r *GoldenConfigRunner) importTree(in services.GoldenConfigTree, replace bool) error {
logger.Trace()

res, err := r.service.GetByName(in.Name)
if err == nil {
if res != nil {
if replace {
if err := r.service.Delete(res.Id); err != nil {
return err
}
} else {
return errors.New(
fmt.Sprintf("gctree with name `%s` already exists, use `--replace` to overwrite it", in.Name),
)
}
} else {
return err
}
}

return r.service.Import(in)
}

func (r *GoldenConfigRunner) getTreeIdFromName(name string) (string, error) {
trees, err := r.service.GetAll()
if err != nil {
Expand Down
63 changes: 63 additions & 0 deletions pkg/services/golden_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package services

import (
"errors"
"fmt"
"net/http"

Expand Down Expand Up @@ -79,14 +80,76 @@ func (svc *GoldenConfigService) Delete(id string) error {
// GetAll calls `GET /configuration_manager/configs`
func (svc *GoldenConfigService) GetAll() ([]GoldenConfigTreeSummary, error) {
logger.Trace()

var res []GoldenConfigTreeSummary
var uri = "/configuration_manager/configs"

if err := svc.client.Get(uri, &res); err != nil {
return nil, err
}

return res, nil
}

func (svc *GoldenConfigService) GetByName(name string) (*GoldenConfigTreeSummary, error) {
logger.Trace()

trees, err := svc.GetAll()
if err != nil {
return nil, err
}

var res *GoldenConfigTreeSummary

for _, ele := range trees {
if ele.Name == name {
res = &ele
break
}
}

if res == nil {
return nil, errors.New("gctree not found")
}

return res, nil
}

// Import will attempt to import a golden configuraiton tree specified by the
// `in` argument and import it to the server. This function will return an
// error or nil if no error is encountered
func (svc *GoldenConfigService) Import(in GoldenConfigTree) error {
logger.Trace()

body := map[string]interface{}{
"trees": []map[string]interface{}{
map[string]interface{}{
"data": []GoldenConfigTree{in},
},
},
"options": map[string]interface{}{},
}

type Response struct {
Status string `json:"status"`
Message string `json:"message"`
}

var res Response

if err := svc.client.PostRequest(&Request{
uri: "/configuration_manager/import/goldenconfigs",
body: &body,
expectedStatusCode: http.StatusOK,
}, &res); err != nil {
return err
}

logger.Info(res.Message)

return nil
}

// Export calls `POST /configuration_manager/export/goldenconfigs`
func (svc *GoldenConfigService) Export(id string) (*GoldenConfigTree, error) {
logger.Trace()
Expand Down