Skip to content

Commit

Permalink
dry-run implementation for tenant import (#15)
Browse files Browse the repository at this point in the history
* tenant dry storage

* fix typo

* remove unused fun

---------

Co-authored-by: Piotr Janus <[email protected]>
  • Loading branch information
piotrek-janus and piotrek-janus authored Mar 29, 2024
1 parent 921d513 commit 2579b10
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 68 deletions.
84 changes: 16 additions & 68 deletions cmd/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ import (
"github.com/cloudentity/cac/internal/cac"
"github.com/cloudentity/cac/internal/cac/api"
"github.com/cloudentity/cac/internal/cac/storage"
"github.com/cloudentity/cac/internal/cac/utils"
"github.com/go-openapi/strfmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/exp/slog"
"os"
)

var (
Expand All @@ -21,8 +18,6 @@ var (
var (
app *cac.Application
data models.Rfc7396PatchOperation
serv *models.TreeServer
tena *models.TreeTenant
err error
)

Expand All @@ -34,78 +29,31 @@ var (
return err
}

if !rootConfig.Tenant {
if serv, err = utils.FromPatchToModel[models.TreeServer](data); err != nil {
return err
}

if err = serv.Validate(strfmt.Default); err != nil {
return err
}

} else {
if tena, err = utils.FromPatchToModel[models.TreeTenant](data); err != nil {
return err
}

if err = tena.Validate(strfmt.Default); err != nil {
return err
}
if err = app.Validator.Validate(&data); err != nil {
return errors.Wrap(err, "failed to validate configuration")
}

if pushConfig.DryRun {
var bts []byte
slog.Info("dry run enabled, storing files to disk instead of pushing to server")

if pushConfig.Out == "-" {
if bts, err = utils.ToYaml(data); err != nil {
return err
}
var (
dryStorage storage.Storage
constr = storage.InitServerStorage
)

_, err = os.Stdout.Write(bts)
return err
if rootConfig.Tenant {
constr = storage.InitTenantStorage
}

if pushConfig.Out != "" {
var (
file *os.File
info os.FileInfo
)

if file, err = os.OpenFile(pushConfig.Out, os.O_RDONLY, 0644); err != nil && !os.IsNotExist(err) {
return err
} else if err == nil {
// file already exists
defer file.Close()

if info, err = file.Stat(); err != nil {
return err
}

if info.IsDir() {
dryStorage := storage.InitServerStorage(&storage.Configuration{
DirPath: pushConfig.Out,
})

if err = dryStorage.Write(cmd.Context(), data, api.WithWorkspace(rootConfig.Workspace)); err != nil {
return err
}

return nil
}
}

if bts, err = utils.ToYaml(data); err != nil {
return err
}

// file does not exist or is not a directory
if err = os.WriteFile(pushConfig.Out, bts, 0644); err != nil {
return err
}

return nil
if dryStorage, err = storage.InitDryStorage(pushConfig.Out, constr); err != nil {
return errors.Wrap(err, "failed to initialize dry storage")
}

if err = dryStorage.Write(cmd.Context(), data, api.WithWorkspace(rootConfig.Workspace)); err != nil {
return errors.Wrap(err, "failed to write configuration")
}

return nil
}

if err = app.Client.Write(
Expand Down
5 changes: 5 additions & 0 deletions internal/cac/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/cloudentity/cac/internal/cac/api"
"github.com/cloudentity/cac/internal/cac/client"
"github.com/cloudentity/cac/internal/cac/config"
"github.com/cloudentity/cac/internal/cac/data"
"github.com/cloudentity/cac/internal/cac/logging"
"github.com/cloudentity/cac/internal/cac/storage"
"golang.org/x/exp/slog"
Expand All @@ -15,6 +16,7 @@ type Application struct {
RootConfig *config.RootConfiguration
Client api.Source
Storage storage.Storage
Validator data.ValidatorApi
}

func InitApp(configPath string, profile string, tenant bool) (app *Application, err error) {
Expand Down Expand Up @@ -49,8 +51,11 @@ func InitApp(configPath string, profile string, tenant bool) (app *Application,

var constructor = storage.InitServerStorage

app.Validator = &data.ServerValidator{}

if tenant {
constructor = storage.InitTenantStorage
app.Validator = &data.TenantValidator{}
}

if app.Config.Storage != nil {
Expand Down
27 changes: 27 additions & 0 deletions internal/cac/data/server_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package data

import (
"github.com/cloudentity/acp-client-go/clients/hub/models"
"github.com/cloudentity/cac/internal/cac/utils"
"github.com/go-openapi/strfmt"
)

type ServerValidator struct{}

var _ ValidatorApi = &ServerValidator{}

func (sv *ServerValidator) Validate(data *models.Rfc7396PatchOperation) error {
var (
err error
serv *models.TreeServer
)
if serv, err = utils.FromPatchToModel[models.TreeServer](*data); err != nil {
return err
}

if err = serv.Validate(strfmt.Default); err != nil {
return err
}

return nil
}
27 changes: 27 additions & 0 deletions internal/cac/data/tenant_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package data

import (
"github.com/cloudentity/acp-client-go/clients/hub/models"
"github.com/cloudentity/cac/internal/cac/utils"
"github.com/go-openapi/strfmt"
)

type TenantValidator struct{}

var _ ValidatorApi = &TenantValidator{}

func (sv *TenantValidator) Validate(data *models.Rfc7396PatchOperation) error {
var (
err error
tenant *models.TreeTenant
)
if tenant, err = utils.FromPatchToModel[models.TreeTenant](*data); err != nil {
return err
}

if err = tenant.Validate(strfmt.Default); err != nil {
return err
}

return nil
}
7 changes: 7 additions & 0 deletions internal/cac/data/validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package data

import "github.com/cloudentity/acp-client-go/clients/hub/models"

type ValidatorApi interface {
Validate(data *models.Rfc7396PatchOperation) error
}
112 changes: 112 additions & 0 deletions internal/cac/storage/dry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package storage

import (
"context"
"github.com/cloudentity/acp-client-go/clients/hub/models"
"github.com/cloudentity/cac/internal/cac/api"
"github.com/cloudentity/cac/internal/cac/utils"
"github.com/pkg/errors"
"os"
)

type DryStorage struct {
DelegatedWriter WriterFunc
}

func InitDryStorage(out string, constr Constructor) (*DryStorage, error) {
var (
delegatedWriter WriterFunc
err error
)

if out == "-" {
delegatedWriter = stdWriter
} else if out != "" {
var (
file *os.File
info os.FileInfo
)

if file, err = os.OpenFile(out, os.O_RDONLY, 0644); err != nil && !os.IsNotExist(err) {
return nil, err
} else if err == nil {
// file already exists
defer file.Close()

if info, err = file.Stat(); err != nil {
return nil, err
}

if info.IsDir() {
dryStorage := constr(&Configuration{
DirPath: out,
})

delegatedWriter = dryStorage.Write
}
}

if delegatedWriter == nil {
delegatedWriter = flatFileWriter(out)
}
} else {
return nil, errors.New("out cannot be empty")
}

return &DryStorage{
DelegatedWriter: delegatedWriter,
}, nil
}

type WriterFunc func(ctx context.Context, data models.Rfc7396PatchOperation, opts ...api.SourceOpt) error

func (d *DryStorage) Write(ctx context.Context, data models.Rfc7396PatchOperation, opts ...api.SourceOpt) error {
return d.DelegatedWriter(ctx, data, opts...)
}

func (d *DryStorage) Read(ctx context.Context, opts ...api.SourceOpt) (models.Rfc7396PatchOperation, error) {
panic("read operation is not implemented for dry storage")
}

var stdWriter = func(ctx context.Context, data models.Rfc7396PatchOperation, opts ...api.SourceOpt) error {
var (
bts []byte
err error
)
if bts, err = utils.ToYaml(data); err != nil {
return err
}

_, err = os.Stdout.Write(bts)
return err
}

var flatFileWriter = func(out string) WriterFunc {
return func(ctx context.Context, data models.Rfc7396PatchOperation, opts ...api.SourceOpt) error {
var (
bts []byte
err error
)

if bts, err = utils.ToYaml(data); err != nil {
return err
}

if err = os.WriteFile(out, bts, 0644); err != nil {
return err
}

if bts, err = utils.ToYaml(data); err != nil {
return err
}

// file does not exist or is not a directory
if err = os.WriteFile(out, bts, 0644); err != nil {
return err
}

return nil
}
}

var _ Storage = &DryStorage{}

0 comments on commit 2579b10

Please sign in to comment.