Skip to content

Commit

Permalink
Added support for creation of user provided services (credentials, lo…
Browse files Browse the repository at this point in the history
…g drain and routes).
  • Loading branch information
David Wu committed Apr 4, 2018
1 parent 2ba05df commit 4ef6024
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 16 deletions.
119 changes: 107 additions & 12 deletions create-services-plugin.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package main

import (
"encoding/json"
"fmt"
"net/url"
"os"
"strings"

"code.cloudfoundry.org/cli/plugin"
)

// Create-Service-Push is the struct implementing the interface defined by the core CLI. It can
// CreateServicePush is the struct implementing the interface defined by the core CLI. It can
// be found at "code.cloudfoundry.org/cli/plugin/plugin.go"
type CreateServicePush struct {
manifest *Manifest
Expand Down Expand Up @@ -70,7 +72,9 @@ func (c *CreateServicePush) Run(cliConnection plugin.CliConnection, args []strin
manifest: &manifest,
cf: cliConnection,
}
createServicesobject.createServices()
if err := createServicesobject.createServices(); err != nil {
os.Exit(1)
}
} else {
fmt.Printf("ERROR: Unable to open %s.\n", manifestFilename)
os.Exit(1)
Expand All @@ -96,14 +100,35 @@ func (c *CreateServicePush) Run(cliConnection plugin.CliConnection, args []strin
}

func (c *CreateServicePush) createServices() error {

var err error
// Detect the type of service and then go and create them.
// credentials: User provided credentials service
// drain: User provided log drain service
// route: User provided route service
// brokered: Brokered service. The type field can be blank to specify this as well.
for _, serviceObject := range c.manifest.Services {
if err := c.createService(serviceObject.ServiceName, serviceObject.Broker, serviceObject.PlanName, serviceObject.JSONParameters); err != nil {
if serviceObject.Type == "credentials" {
err = c.createUserProvidedCredentialsService(serviceObject.ServiceName, serviceObject.Credentials)
} else if serviceObject.Type == "drain" {
err = c.createUserProvidedLogDrainService(serviceObject.ServiceName, serviceObject.Url)
} else if serviceObject.Type == "route" {
err = c.createUserProvidedRouteService(serviceObject.ServiceName, serviceObject.Url)
} else {
if serviceObject.Type == "brokered" || serviceObject.Type == "" {
err = c.createService(serviceObject.ServiceName, serviceObject.Broker, serviceObject.PlanName, serviceObject.JSONParameters)
} else {
err = fmt.Errorf("Service Type: %s unsupported", serviceObject.Type)
}
}

// If we encounter any errors, quit immediately, so errors are caught early.
if err != nil {
fmt.Printf("Create Service Error: %+v \n", err)
break
}
}

return nil
return err
}

func (c *CreateServicePush) run(args ...string) error {
Expand All @@ -116,30 +141,99 @@ func (c *CreateServicePush) run(args ...string) error {
return err
}

func (c *CreateServicePush) createUserProvidedCredentialsService(name string, credentials map[string]string) error {
fmt.Printf("%s - ", name)
s, err := c.cf.GetServices()
if err != nil {
return err
}

for _, svc := range s {
if svc.Name == name {
fmt.Print("already exists...skipping creation\n")
return nil
}
}

fmt.Print("will now be created as a user provided credential service.\n")
credentialsJSON, _ := json.Marshal(credentials)

return c.run("cups", name, "-p", string(credentialsJSON))
}

func (c *CreateServicePush) createUserProvidedRouteService(name, urlString string) error {
fmt.Printf("%s - ", name)
s, err := c.cf.GetServices()
if err != nil {
return err
}

for _, svc := range s {
if svc.Name == name {
fmt.Print("already exists...skipping creation\n")
return nil
}
}

// Check to ensure that the url begins with HTTPS because that is the only scheme supported.
urlStruct, err := url.Parse(urlString)

if err != nil {
return err
}

if strings.ToLower(urlStruct.Scheme) != "https" {
return fmt.Errorf("route scheme not specified or unsupported. User provided route service only supports https")
}

fmt.Print("will now be created as a user provided route service.\n")

return c.run("cups", name, "-r", urlString)
}

func (c *CreateServicePush) createUserProvidedLogDrainService(name, urlString string) error {
fmt.Printf("%s - ", name)
s, err := c.cf.GetServices()
if err != nil {
return err
}

for _, svc := range s {
if svc.Name == name {
fmt.Print("already exists...skipping creation\n")
return nil
}
}

fmt.Print("will now be created as a user provided log drain service.\n")

return c.run("cups", name, "-l", urlString)
}

func (c *CreateServicePush) createService(name, broker, plan, JSONParam string) error {
fmt.Printf("%s - ", name)
s, err := c.cf.GetServices()
if err != nil {
return err
}

for _, svc := range s {
if svc.Name == name {
fmt.Printf("%s already exists.\n", name)
fmt.Print("already exists...skipping creation\n")
return nil
}
}

fmt.Printf("%s will now be created.\n", name)
fmt.Printf("will now be created as a brokered service.\n")

var result error
if JSONParam == "" {
result = c.run("create-service", broker, plan, name)
err = c.run("create-service", broker, plan, name)
} else {
result = c.run("create-service", broker, plan, name, "-c", JSONParam)
err = c.run("create-service", broker, plan, name, "-c", JSONParam)
}

if result != nil {
return result
if err != nil {
return err
}

pb := NewProgressSpinner(os.Stdout)
Expand Down Expand Up @@ -194,6 +288,7 @@ func (c *CreateServicePush) GetMetadata() plugin.PluginMetadata {
Commands: []plugin.Command{
{
Name: "create-service-push",
Alias: "csp",
HelpText: "Works in the same manner as cf push, except that it will create services defined in a services-manifest.yml file first before performing a cf push.",

// UsageDetails is optional
Expand Down
12 changes: 8 additions & 4 deletions manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ import (
)

type Service struct {
ServiceName string `yaml:"name"`
Broker string `yaml:"broker"`
PlanName string `yaml:"plan"`
JSONParameters string `yaml:"parameters"`
ServiceName string `yaml:"name"`
Type string `yaml:"type"` //brokered, credentials, drain, route. "blank" == brokered
Broker string `yaml:"broker"`
PlanName string `yaml:"plan"`
Url string `yaml:"url"`
Credentials map[string]string `yaml:"credentials"`
JSONParameters string `yaml:"parameters"`
}

type Manifest struct {
Services []Service `yaml:"create-services"`
}
Expand Down

0 comments on commit 4ef6024

Please sign in to comment.