Skip to content

Commit

Permalink
Support backend context for typeinstance commands (#699)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateusz Kuziemko authored Apr 14, 2022
1 parent 8b42710 commit 37750de
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 23 deletions.
44 changes: 40 additions & 4 deletions cmd/cli/cmd/typeinstance/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"fmt"
"io"
"os"
"strings"

"capact.io/capact/internal/cli/client"
"capact.io/capact/internal/cli/config"
gqllocalapi "capact.io/capact/pkg/hub/api/graphql/local"
storagebackend "capact.io/capact/pkg/hub/storage-backend"
"capact.io/capact/pkg/sdk/validation"

"github.com/AlecAivazis/survey/v2"
Expand Down Expand Up @@ -83,20 +85,36 @@ func editTI(ctx context.Context, opts editOptions, w io.Writer) error {
func typeInstanceViaEditor(ctx context.Context, cli client.Hub, tiID string) ([]gqllocalapi.UpdateTypeInstancesInput, error) {
out, err := cli.FindTypeInstance(ctx, tiID)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "while finding TypeInstance")
}
if out == nil {
return nil, fmt.Errorf("TypeInstance %s not found", tiID)
}

rawInput, err := yaml.Marshal(mapTypeInstanceToUpdateType(out))
backendData, err := storagebackend.NewTypeInstanceValue(ctx, cli, out)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "while fetching storage backend data")
}

updateTI := mapTypeInstanceToUpdateType(out)

var valueData string
if backendData != nil && !backendData.AcceptValue {
valueData, err = getCommentedOutTypeInstanceValue(&updateTI)
if err != nil {
return nil, errors.Wrap(err, "while getting commented out TypeInstance value")
}
}

setTypeInstanceValueForMarshaling(backendData, &updateTI)
rawInput, err := yaml.Marshal(updateTI)
if err != nil {
return nil, errors.Wrap(err, "while marshaling updated TypeInstance")
}

prompt := &survey.Editor{
Message: "Edit TypeInstance in YAML format",
Default: string(rawInput),
Default: fmt.Sprintf("%s%s", string(rawInput), valueData),
AppendDefault: true,
HideDefault: true,
}
Expand All @@ -117,6 +135,24 @@ func typeInstanceViaEditor(ctx context.Context, cli client.Hub, tiID string) ([]
}, nil
}

func getCommentedOutTypeInstanceValue(in *gqllocalapi.UpdateTypeInstancesInput) (string, error) {
type valueOnly struct {
Value interface{} `json:"value,omitempty"`
}
encodedValue, err := yaml.Marshal(valueOnly{in.TypeInstance.Value})
if err != nil {
return "", errors.Wrap(err, "while marshaling storage backend value")
}
lines := strings.Split(string(encodedValue), "\n")
for i := range lines {
if lines[i] == "" {
continue
}
lines[i] = "# " + lines[i]
}
return strings.Join(lines, "\n"), nil
}

func isValidUpdateTypeInstancesInput(val interface{}) error {
str, ok := val.(string)
if !ok {
Expand Down
31 changes: 19 additions & 12 deletions cmd/cli/cmd/typeinstance/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/fatih/color"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"capact.io/capact/internal/cli"
Expand All @@ -18,6 +19,7 @@ import (
cliprinter "capact.io/capact/internal/cli/printer"
gqllocalapi "capact.io/capact/pkg/hub/api/graphql/local"
"capact.io/capact/pkg/hub/client/local"
storagebackend "capact.io/capact/pkg/hub/storage-backend"
)

const (
Expand Down Expand Up @@ -66,14 +68,26 @@ func NewGet() *cobra.Command {
return ErrTableFormatWithExportFlag
}

tis, err := getTI(cmd.Context(), opts, resourcePrinter.PrintFormat())
ctx := cmd.Context()
server := config.GetDefaultContext()
cli, err := client.NewHub(server)
if err != nil {
return err
return errors.Wrap(err, "while creating hub client")
}

tis, err := getTI(ctx, cli, opts, resourcePrinter.PrintFormat())
if err != nil {
return errors.Wrap(err, "while getting TypeInstance")
}

if opts.ExportToUpdateFormat {
for idx := range tis {
conv := mapTypeInstanceToUpdateType(&tis[idx])
backendData, err := storagebackend.NewTypeInstanceValue(cmd.Context(), cli, &tis[idx])
if err != nil {
return errors.Wrap(err, "while fetching storage backend data")
}
setTypeInstanceValueForMarshaling(backendData, &conv)
fmt.Fprintln(out, yamlFileSeparator)
if err := resourcePrinter.Print(conv); err != nil {
return err
Expand All @@ -94,14 +108,7 @@ func NewGet() *cobra.Command {
return cmd
}

func getTI(ctx context.Context, opts GetOptions, format cliprinter.PrintFormat) ([]gqllocalapi.TypeInstance, error) {
server := config.GetDefaultContext()

hubCli, err := client.NewHub(server)
if err != nil {
return nil, err
}

func getTI(ctx context.Context, cli client.Hub, opts GetOptions, format cliprinter.PrintFormat) ([]gqllocalapi.TypeInstance, error) {
var listOpts []local.TypeInstancesOption
if format == cliprinter.TableFormat {
listOpts = append(listOpts, local.WithFields(tableRequiredFields))
Expand All @@ -111,7 +118,7 @@ func getTI(ctx context.Context, opts GetOptions, format cliprinter.PrintFormat)
if format != cliprinter.TableFormat {
printHugePayloadWarning()
}
return hubCli.ListTypeInstances(ctx, &gqllocalapi.TypeInstanceFilter{}, listOpts...)
return cli.ListTypeInstances(ctx, &gqllocalapi.TypeInstanceFilter{}, listOpts...)
}

var (
Expand All @@ -121,7 +128,7 @@ func getTI(ctx context.Context, opts GetOptions, format cliprinter.PrintFormat)

// TODO: make it client-side
for _, id := range opts.RequestedTypeInstancesIDs {
ti, err := hubCli.FindTypeInstance(ctx, id, listOpts...)
ti, err := cli.FindTypeInstance(ctx, id, listOpts...)
if err != nil {
errs = append(errs, err)
continue
Expand Down
39 changes: 32 additions & 7 deletions cmd/cli/cmd/typeinstance/type_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package typeinstance

import (
gqllocalapi "capact.io/capact/pkg/hub/api/graphql/local"
storagebackend "capact.io/capact/pkg/hub/storage-backend"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -33,13 +34,6 @@ func mapTypeInstanceToUpdateType(in *gqllocalapi.TypeInstance) gqllocalapi.Updat
ID: in.ID,
}

mapSpecValue := func() interface{} {
if in.LatestResourceVersion.Spec == nil {
return nil
}
return in.LatestResourceVersion.Spec.Value
}

mapAttrs := func() []*gqllocalapi.AttributeReferenceInput {
if in.LatestResourceVersion.Metadata == nil || in.LatestResourceVersion.Metadata.Attributes == nil {
return []*gqllocalapi.AttributeReferenceInput{}
Expand All @@ -57,16 +51,47 @@ func mapTypeInstanceToUpdateType(in *gqllocalapi.TypeInstance) gqllocalapi.Updat
return out
}

mapSpecValue := func() interface{} {
if in.LatestResourceVersion.Spec == nil {
return nil
}
return in.LatestResourceVersion.Spec.Value
}

mapBackend := func() *gqllocalapi.UpdateTypeInstanceBackendInput {
if in.LatestResourceVersion.Spec.Backend == nil {
return nil
}
return &gqllocalapi.UpdateTypeInstanceBackendInput{
Context: in.LatestResourceVersion.Spec.Backend.Context,
}
}

if in.LatestResourceVersion != nil {
out.TypeInstance = &gqllocalapi.UpdateTypeInstanceInput{
Attributes: mapAttrs(),
Value: mapSpecValue(),
Backend: mapBackend(),
}
}

return out
}

// setTypeInstanceValueForMarshaling sets TypeInstance value based on backend data.
func setTypeInstanceValueForMarshaling(typeInstanceValue *storagebackend.TypeInstanceValue, in *gqllocalapi.UpdateTypeInstancesInput) {
if typeInstanceValue == nil {
in.TypeInstance.Backend = nil
return
}
if typeInstanceValue.ContextSchema == nil {
in.TypeInstance.Backend = nil
}
if !typeInstanceValue.AcceptValue {
in.TypeInstance.Value = nil
}
}

func panicOnError(err error) {
if err != nil {
panic(err)
Expand Down
30 changes: 30 additions & 0 deletions pkg/hub/storage-backend/types.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
package storagebackend

import (
"context"
"encoding/json"

"capact.io/capact/internal/cli/client"
gqllocalapi "capact.io/capact/pkg/hub/api/graphql/local"
"github.com/pkg/errors"
)

// TypeInstanceValue defines properties for TypeInstance value for every Storage Backend.
type TypeInstanceValue struct {
URL string `json:"url"`
AcceptValue bool `json:"acceptValue"`
ContextSchema interface{} `json:"contextSchema"`
}

// NewTypeInstanceValue returns a new TypeInstanceValue instance based on backend used by passed TypeInstance.
func NewTypeInstanceValue(ctx context.Context, cli client.Hub, typeInstance *gqllocalapi.TypeInstance) (*TypeInstanceValue, error) {
var typeInstanceValue *TypeInstanceValue
if typeInstance.Backend == nil || typeInstance.Backend.Abstract {
return nil, nil
}
backendTI, err := cli.FindTypeInstance(ctx, typeInstance.Backend.ID)
if err != nil {
return nil, errors.Wrap(err, "while finding backend TypeInstance")
}
valueBytes, err := json.Marshal(backendTI.LatestResourceVersion.Spec.Value)
if err != nil {
return nil, errors.Wrap(err, "while marshaling storage backend value")
}
err = json.Unmarshal(valueBytes, &typeInstanceValue)
if err != nil {
return nil, errors.Wrap(err, "while unmarshaling storage backend value")
}
return typeInstanceValue, nil
}

0 comments on commit 37750de

Please sign in to comment.