Skip to content

Commit

Permalink
refactor: extract common create behavior & use it for capability and …
Browse files Browse the repository at this point in the history
…link
  • Loading branch information
metacosm committed Oct 7, 2019
1 parent 1cf7fe0 commit 5616236
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 85 deletions.
81 changes: 81 additions & 0 deletions pkg/cmdutil/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cmdutil

import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"halkyon.io/hal/pkg/log"
"halkyon.io/hal/pkg/ui"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record/util"
"strings"
"time"
)

const createCommandName = "create"

type Creator interface {
Runnable
GeneratePrefix() string
Build() runtime.Object
}

type CreateOptions struct {
*GenericOperationOptions
Delegate Creator
}

func NewCreateOptions(resourceType string, client HalkyonEntity) *CreateOptions {
c := &CreateOptions{}
c.GenericOperationOptions = &GenericOperationOptions{
ResourceType: resourceType,
Client: client,
operationName: createCommandName,
delegate: c,
}
return c
}

func (o *CreateOptions) Complete(name string, cmd *cobra.Command, args []string) error {
if err := o.Delegate.Complete(name, cmd, args); err != nil {
return err
}
if len(args) == 0 {
o.Name = ui.Ask("Change default name", o.Name, o.generateName())
} else {
o.Name = args[0]
}

return nil
}

func (o *CreateOptions) Validate() error {
if err := o.Delegate.Validate(); err != nil {
return err
}

err := o.Client.Get(o.Name, v1.GetOptions{})
if err != nil && !util.IsKeyNotFoundError(errors.Cause(err)) {
return err
}
return fmt.Errorf("a %s named '%s' already exists, please select another name", o.ResourceType, o.Name)
}

func (o *CreateOptions) Run() error {
err := o.Client.Create(o.Delegate.Build())
if err == nil {
log.Successf("Successfully created '%s' %s", o.Name, o.ResourceType)
}
return err
}

func (o *CreateOptions) generateName() string {
return fmt.Sprintf("%s-%s-%d", o.Delegate.GeneratePrefix(), o.ResourceType, time.Now().UnixNano())
}

func NewGenericCreate(fullParentName string, o *CreateOptions) *cobra.Command {
create := NewGenericOperation(fullParentName, o.GenericOperationOptions)
create.Flags().StringVarP(&o.Name, "name", "n", "", fmt.Sprintf("%s name", strings.Title(o.ResourceType)))
return create
}
2 changes: 2 additions & 0 deletions pkg/cmdutil/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"github.com/spf13/cobra"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ktemplates "k8s.io/kubectl/pkg/util/templates"
"strings"
)
Expand Down Expand Up @@ -57,6 +58,7 @@ func NewGenericOperation(fullParentName string, o *GenericOperationOptions) *cob

type HalkyonEntity interface {
Get(string, v1.GetOptions) error
Create(runtime.Object) error
Delete(string, *v1.DeleteOptions) error
GetKnown() []string
GetNamespace() string
Expand Down
73 changes: 30 additions & 43 deletions pkg/hal/cli/capability/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,47 @@ import (
halkyon "halkyon.io/api/v1beta1"
"halkyon.io/hal/pkg/cmdutil"
"halkyon.io/hal/pkg/k8s"
"halkyon.io/hal/pkg/log"
"halkyon.io/hal/pkg/ui"
"halkyon.io/hal/pkg/validation"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ktemplates "k8s.io/kubectl/pkg/util/templates"
"strings"
"time"
)

const createCommandeName = "create"

type createOptions struct {
category string
subCategory string
version string
paramPairs []string
parameters []halkyon.NameValuePair
name string
*cmdutil.CreateOptions
}

var (
capabilityExample = ktemplates.Examples(` # Create a new database capability of type postgres 10 and sets up some parameters as the name of the database and the user/password to connect.
%[1]s -n db-capability -g database -t postgres -v 10 -p DB_NAME=sample-db -p DB_PASSWORD=admin -p DB_USER=admin`)
)

func (o *createOptions) GeneratePrefix() string {
return o.subCategory
}

func (o *createOptions) Build() runtime.Object {
return &v1beta1.Capability{
ObjectMeta: v1.ObjectMeta{
Name: o.Name,
Namespace: o.CreateOptions.Client.GetNamespace(),
},
Spec: v1beta1.CapabilitySpec{
Category: v1beta1.DatabaseCategory, // todo: replace hardcoded value
Type: v1beta1.PostgresType, // todo: replace hardcoded value
Version: o.version,
Parameters: o.parameters,
},
}
}

func (o *createOptions) Complete(name string, cmd *cobra.Command, args []string) error {
o.selectOrCheckExisting(&o.category, "Category", o.getCategories(), o.isValidCategory)
o.selectOrCheckExisting(&o.subCategory, "Type", o.getTypesFor(o.category), o.isValidTypeGivenCategory)
Expand All @@ -43,9 +59,6 @@ func (o *createOptions) Complete(name string, cmd *cobra.Command, args []string)
}
}

generated := fmt.Sprintf("%s-capability-%d", o.subCategory, time.Now().UnixNano())
o.name = ui.Ask("Name", o.name, generated)

return nil
}

Expand Down Expand Up @@ -89,30 +102,6 @@ func (p parameterInfo) AsValidatable() validation.Validatable {
return p.Validatable
}

func (o *createOptions) Run() error {
client := k8s.GetClient()
c, err := client.HalkyonCapabilityClient.Capabilities(client.Namespace).Create(&v1beta1.Capability{
ObjectMeta: v1.ObjectMeta{
Name: o.name,
Namespace: client.Namespace,
},
Spec: v1beta1.CapabilitySpec{
Category: v1beta1.DatabaseCategory, // todo: replace hardcoded value
Type: v1beta1.PostgresType, // todo: replace hardcoded value
Version: o.version,
Parameters: o.parameters,
},
})

if err != nil {
return err
}

log.Successf("Created capability %s", c.Name)

return nil
}

func (o *createOptions) selectOrCheckExisting(parameterValue *string, capitalizedParameterName string, validValues []string, validator func() bool) {
if len(*parameterValue) == 0 {
*parameterValue = ui.Select(capitalizedParameterName, validValues)
Expand Down Expand Up @@ -227,20 +216,18 @@ func (o *createOptions) addValueFor(prop parameterInfo) {
}

func NewCmdCreate(parent string) *cobra.Command {
c := k8s.GetClient()
o := &createOptions{}
capability := &cobra.Command{
Use: fmt.Sprintf("%s [flags]", createCommandeName),
Short: "Create a new capability",
Long: `Create a new capability`,
Args: cobra.NoArgs,
Example: fmt.Sprintf(capabilityExample, cmdutil.CommandName(createCommandeName, parent)),
Run: func(cmd *cobra.Command, args []string) {
cmdutil.GenericRun(o, cmd, args)
},
}
generic := cmdutil.NewCreateOptions("capability", client{
client: c.HalkyonCapabilityClient.Capabilities(c.Namespace),
ns: c.Namespace,
})
generic.Delegate = o
o.CreateOptions = generic
capability := cmdutil.NewGenericCreate(parent, generic)
capability.Example = fmt.Sprintf(capabilityExample, cmdutil.CommandName(capability.Name(), parent))

capability.Flags().StringVarP(&o.category, "category", "g", "", "Capability category e.g. 'database'")
capability.Flags().StringVarP(&o.name, "name", "n", "", "Capability name")
capability.Flags().StringVarP(&o.subCategory, "type", "t", "", "Capability type e.g. 'postgres'")
capability.Flags().StringVarP(&o.version, "version", "v", "", "Capability version")
capability.Flags().StringSliceVarP(&o.paramPairs, "parameters", "p", []string{}, "Capability-specific parameters")
Expand Down
7 changes: 7 additions & 0 deletions pkg/hal/cli/capability/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ package capability

import (
"halkyon.io/api/capability/clientset/versioned/typed/capability/v1beta1"
v1beta12 "halkyon.io/api/capability/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

type client struct {
client v1beta1.CapabilityInterface
ns string
}

func (lc client) Create(toCreate runtime.Object) error {
_, err := lc.client.Create(toCreate.(*v1beta12.Capability))
return err
}

func (lc client) Get(name string, options v1.GetOptions) error {
_, err := lc.client.Get(name, options)
return err
Expand Down
7 changes: 7 additions & 0 deletions pkg/hal/cli/component/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ package component

import (
"halkyon.io/api/component/clientset/versioned/typed/component/v1beta1"
v1beta12 "halkyon.io/api/component/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

type client struct {
client v1beta1.ComponentInterface
ns string
}

func (lc client) Create(toCreate runtime.Object) error {
_, err := lc.client.Create(toCreate.(*v1beta12.Component))
return err
}

func (lc client) Get(name string, options v1.GetOptions) error {
_, err := lc.client.Get(name, options)
return err
Expand Down
Loading

0 comments on commit 5616236

Please sign in to comment.