Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Citr support #6

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
97 changes: 78 additions & 19 deletions restore/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/cloudfoundry/cli/plugin"
"github.com/fatih/color"
"github.com/SAP/service-fabrik-cli-plugin/constants"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of SAP this should be cloudfoundry-incubator , correct?

"github.com/SAP/service-fabrik-cli-plugin/errors"
"github.com/SAP/service-fabrik-cli-plugin/guidTranslator"
"github.com/SAP/service-fabrik-cli-plugin/helper"
"github.com/cloudfoundry/cli/plugin"
"github.com/fatih/color"
"io/ioutil"
"net/http"
"os"
"strconv"
"strings"
"time"
)
Expand Down Expand Up @@ -78,13 +80,13 @@ func getConfiguration() Configuration {
func GetHttpClient() *http.Client {
//Skip ssl verification.
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: GetskipSslFlag()},
Proxy: http.ProxyFromEnvironment,
},
Timeout: time.Duration(180) * time.Second,
}
return client
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: GetskipSslFlag()},
Proxy: http.ProxyFromEnvironment,
},
Timeout: time.Duration(180) * time.Second,
}
return client
}

func GetResponse(client *http.Client, req *http.Request) *http.Response {
Expand All @@ -96,18 +98,71 @@ func GetResponse(client *http.Client, req *http.Request) *http.Response {
return resp
}

func (c *RestoreCommand) StartRestore(cliConnection plugin.CliConnection, serviceInstanceName string, backupId string) {
func (c *RestoreCommand) StartRestore(cliConnection plugin.CliConnection, serviceInstanceName string, backupId string, timeStamp string, isGuidOperation bool, instanceGuidOperation bool, instanceNameOperation bool, instanceGuid string, instanceName string, deletedFlag bool) {
fmt.Println("Starting restore for ", AddColor(serviceInstanceName, cyan), "...")

var source_instance_id string = ""

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is snake casing used here ?

if instanceGuidOperation == true {
var serviceInstanceName string = ""
serviceInstanceName = guidTranslator.FindInstanceName(cliConnection, instanceGuid, nil)
fmt.Println("Instance Name = ", serviceInstanceName)
if serviceInstanceName == "" {
fmt.Println(AddColor("FAILED", red))
fmt.Println("Error - No service instance found with service instance guid = ", instanceGuid)
os.Exit(7)
} else {
source_instance_id = instanceGuid
}
}
if instanceNameOperation == true {
guid := guidTranslator.FindInstanceGuid(cliConnection, instanceName, nil, "")
guid = strings.Trim(guid, ",")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are below 2 trim's required ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the guid comes in form - "guid",
so the first trim removes ',' (comma) and the second trim removes '"' (double quotes).

guid = strings.Trim(guid, "\"")
source_instance_id = guid
}
if deletedFlag == true {
var guidMap map[string]string = guidTranslator.FindDeletedInstanceGuid(cliConnection, instanceName, nil, "")
if len(guidMap) > 1 {
fmt.Println(AddColor("FAILED", constants.Red))
fmt.Println("" + instanceName + " maps to multiple instance GUIDs, please use 'cf instance-events --delete' to list all instance delete events, get required instance guid from the list and then use 'cf list-backup --guid GUID' to fetch backups list.")
fmt.Println("Enter 'cf backup' to check the list of commands and their usage.")
os.Exit(1)
} else {
for k, _ := range guidMap {
guid := k
guid = strings.Trim(guid, ",")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above .. why the trim's are required ?

also if required , can you extract this to a util function and reuse it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added new method.

guid = strings.Trim(guid, "\"")
source_instance_id = guid
}
}
}
if helper.GetAccessToken(helper.ReadConfigJsonFile()) == "" {
errors.NoAccessTokenError("Access Token")
}

var userSpaceGuid string = helper.GetSpaceGUID(helper.ReadConfigJsonFile())
client := GetHttpClient()

var jsonprep string = `{"backup_guid": "` + backupId + `"}`
var jsonStr = []byte(jsonprep)
var req_body = bytes.NewBuffer(jsonStr)
var req_body = bytes.NewBuffer([]byte(""))
if isGuidOperation == true {
var jsonPrep string = `{"backup_guid": "` + backupId + `"}`
var jsonStr = []byte(jsonPrep)
req_body = bytes.NewBuffer(jsonStr)
} else {
parsedTimestamp, err := time.Parse(time.RFC3339, timeStamp)
if err != nil {
fmt.Println(AddColor("FAILED", red))
fmt.Println(err)
fmt.Println("Please enter time in ISO8061 format, example - 2018-11-12T11:45:26.371Z, 2018-11-12T11:45:26Z")
return
}
var epochTime string = strconv.FormatInt(parsedTimestamp.UnixNano()/1000000, 10)
var jsonPrep string = ""
if source_instance_id != "" {
jsonPrep = `{"time_stamp": "` + epochTime + `", "space_guid": "` + userSpaceGuid + `", "source_instance_id": "` + source_instance_id + `"}`
} else {
jsonPrep = `{"time_stamp": "` + epochTime + `", "space_guid": "` + userSpaceGuid + `"}`
}
var jsonStr = []byte(jsonPrep)
req_body = bytes.NewBuffer(jsonStr)
}

var guid string = guidTranslator.FindInstanceGuid(cliConnection, serviceInstanceName, nil, "")
guid = strings.TrimRight(guid, ",")
Expand All @@ -129,12 +184,16 @@ func (c *RestoreCommand) StartRestore(cliConnection plugin.CliConnection, servic
fmt.Println(AddColor("FAILED", red))
var message string = string(body)
var parts []string = strings.Split(message, ":")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to check the size and then access third element of array right ? what if the response from the API changes , like it might already if we merge the broker code ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

fmt.Println(parts[2])
fmt.Println("Error - ", parts[3])
}

if resp.Status == "202 Accepted" {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we check like ignoring case || contains 202

fmt.Println(AddColor("OK", green))
fmt.Println("Restore has been initiated for the instance name:", AddColor(serviceInstanceName, cyan), " and from the backup id:", AddColor(backupId, cyan))
if isGuidOperation == true {
fmt.Println("Restore has been initiated for the instance name:", AddColor(serviceInstanceName, cyan), " and from the backup id:", AddColor(backupId, cyan))
} else {
fmt.Println("Restore has been initiated for the instance name:", AddColor(serviceInstanceName, cyan), " using time stamp:", AddColor(timeStamp, cyan))
}
fmt.Println("Please check the status of restore by entering 'cf service SERVICE_INSTANCE_NAME'")
}

Expand Down Expand Up @@ -174,7 +233,7 @@ func (c *RestoreCommand) AbortRestore(cliConnection plugin.CliConnection, servic
fmt.Println(AddColor("FAILED", red))
var message string = string(body)
var parts []string = strings.Split(message, ":")
fmt.Println(parts[2])
fmt.Println(parts[3])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above.

}

if resp.Status == "202 Accepted" {
Expand Down
72 changes: 60 additions & 12 deletions service-fabrik-plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,66 @@ func (serviceFabrikPlugin *ServiceFabrikPlugin) Run(cliConnection plugin.CliConn
//Internally split into start and abort.
switch cmds[0] {
case "start":
if argLength != 3 {
errors.IncorrectNumberOfArguments()
}
fmt.Println("Are you sure you want to start restore? (y/n)")
var userChoice string
fmt.Scanln(&userChoice)
if userChoice == "y" {
restore.NewRestoreCommand(cliConnection).StartRestore(cliConnection, args[1], args[2])
if argLength == 4 {
if args[2] == "--backup_guid" {
fmt.Println("Are you sure you want to start restore? (y/n)")
var userChoice string
fmt.Scanln(&userChoice)
if userChoice == "y" {
restore.NewRestoreCommand(cliConnection).StartRestore(cliConnection, args[1], args[3], "", true, false, false, "", "", false)
} else {
os.Exit(7)
}
} else if args[2] == "--timestamp" {
fmt.Println("Are you sure you want to start restore? (y/n)")
var userChoice string
fmt.Scanln(&userChoice)
if userChoice == "y" {
restore.NewRestoreCommand(cliConnection).StartRestore(cliConnection, args[1], "", args[3], false, false, false, "", "", false)
} else {
os.Exit(7)
}
} else {
errors.InvalidArgument()
}
} else if argLength == 6 {
if args[4] == "--from-instance-id" {
fmt.Println("Are you sure you want to start restore? (y/n)")
var userChoice string
fmt.Scanln(&userChoice)
if userChoice == "y" {
restore.NewRestoreCommand(cliConnection).StartRestore(cliConnection, args[1], "", args[3], false, true, false, args[5], "", false)
} else {
os.Exit(7)
}
} else if args[4] == "--from-instance" {
fmt.Println("Are you sure you want to start restore? (y/n)")
var userChoice string
fmt.Scanln(&userChoice)
if userChoice == "y" {
restore.NewRestoreCommand(cliConnection).StartRestore(cliConnection, args[1], "", args[3], false, false, true, "", args[5], false)
} else {
os.Exit(7)
}
} else {
errors.InvalidArgument()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we provide a sample help command instead of throwing only InvalidArgument() ?

}
} else if argLength == 7 {
if args[6] == "--deleted" && args[4] == "--from-instance" {
fmt.Println("Are you sure you want to start restore? (y/n)")
var userChoice string
fmt.Scanln(&userChoice)
if userChoice == "y" {
restore.NewRestoreCommand(cliConnection).StartRestore(cliConnection, args[1], "", args[3], false, false, false, "", args[5], true)
} else {
os.Exit(7)
}
} else {
errors.InvalidArgument()
}
} else {
os.Exit(7)
errors.IncorrectNumberOfArguments()
}

case "abort":
if argLength != 2 {
errors.IncorrectNumberOfArguments()
Expand Down Expand Up @@ -215,7 +263,7 @@ func (serviceFabrikPlugin *ServiceFabrikPlugin) GetMetadata() plugin.PluginMetad
Name: "ServiceFabrikPlugin",
Version: setVersion(Version),
Commands: []plugin.Command{
{ // required to be a registered command
{ // required to be a registered command
Name: "start-backup",
HelpText: "Start backup of a service instance",
UsageDetails: plugin.Usage{
Expand Down Expand Up @@ -261,7 +309,7 @@ func (serviceFabrikPlugin *ServiceFabrikPlugin) GetMetadata() plugin.PluginMetad
Name: "start-restore",
HelpText: "Start restore of a service instance",
UsageDetails: plugin.Usage{
Usage: "cf start-restore SERVICE_INSTANCE_NAME BACKUP_ID",
Usage: "cf start-restore SERVICE_INSTANCE_NAME --backup_guid BACKUP_ID \n cf start-restore SERVICE_INSTANCE_NAME --timestamp TIME_STAMP",
},
},
{
Expand Down