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
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ This is a [Cloud Foundry CLI](https://github.com/cloudfoundry/cli) plugin for pe
## Building the plugin
Clone this repo and build it. For this execute following commands on Linux or Mac OS X system
```
$ go get github.com/SAP/service-fabrik-cli-plugin
$ cd $GOPATH/src/github.com/SAP/service-fabrik-cli-plugin
$ go get github.com/cloudfoundry-incubator/service-fabrik-cli-plugin
$ cd $GOPATH/src/github.com/cloudfoundry-incubator/service-fabrik-cli-plugin
$ go build .
```

The above will clone your repo into default $GOPATH. If you want to setup a different $GOPATH and work on that, then execute following commands on a Linux or Mac OS X system:

```
$ mkdir -p service-fabrik-cli-plugin/src/github.com/SAP/
$ mkdir -p service-fabrik-cli-plugin/src/github.com/cloudfoundry-incubator/
$ export GOPATH=$(pwd)/service-fabrik-cli-plugin:$GOPATH
$ cd service-fabrik-cli-plugin/src/github.com/SAP/
$ git clone https://github.com/SAP/service-fabrik-cli-plugin.git
Expand All @@ -36,15 +36,15 @@ This will generate a binary executable with the name `service-fabrik-cli-plugin`

For Windows
```
cf install-plugin C:\Users\[username]\github.com\SAP\service-fabrik-cli-plugin\servicefabrik_cli_plugin_windows_amd64.exe
cf install-plugin C:\Users\[username]\github.com\cloudfoundry-incubator\service-fabrik-cli-plugin\servicefabrik_cli_plugin_windows_amd64.exe
```
For Mac
```
cf install-plugin ~/github.com/SAP/service-fabrik-cli-plugin/servicefabrik_cli_plugin_darwin_amd64
cf install-plugin ~/github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/servicefabrik_cli_plugin_darwin_amd64
```
For Linux
```
cf install-plugin ~/github.com/SAP/service-fabrik-cli-plugin/servicefabrik_cli_plugin_linux_amd64
cf install-plugin ~/github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/servicefabrik_cli_plugin_linux_amd64
```
The installation instructions given here imply that the working directory is the home directory. Kindly change it to the proper directory structure as given here, if it is not so.

Expand Down Expand Up @@ -77,17 +77,21 @@ Command Name | Command Description
`cf instance-events --create` | List all create service instance events in the space.
`cf instance-events --update` | List all update service instance events in the space.
`cf instance-events --delete` | List all delete service instance events in the space.
` cf start-restore SERVICE_INSTANCE_NAME BACKUP_ID ` | Start restore of a service-fabrik service instance from the given backup id.
` cf start-restore SERVICE_INSTANCE_NAME --backup-guid BACKUP_ID ` | Start restore of a service-fabrik service instance from the given backup id.
` cf start-restore SERVICE_INSTANCE_NAME --timestamp TIME_STAMP `| Start restore of a service-fabrik service instance using the given timestamp for time based recovery.
` cf start-restore SERVICE_INSTANCE_NAME --timestamp TIME_STAMP --source SOURCE_SERVICE_INSTANCE_NAME` | Start restore of a service-fabrik service instance using the given timestamp and using backup of source service instance.
` cf start-restore SERVICE_INSTANCE_NAME --timestamp TIME_STAMP --source-id SOURCE_SERVICE_INSTANCE_GUID` | Start restore of a service-fabrik service instance using the given timestamp and from backup of given source service instance guid.
` cf start-restore SERVICE_INSTANCE_NAME --timestamp TIME_STAMP --source SOURCE_SERVICE_INSTANCE_NAME --deleted` | Start restore of a service-fabrik service instance using the given timestamp and using backup of deleted source service instance.
` cf abort-restore SERVICE_INSTANCE_NAME` | Abort restore of a service-fabrik service instance.

For more information, see the command help output available via `cf [command] --help` or `cf help [command]`.

# Further Reading
User Documentation: [user_documentation_cf_cli_plugin.md](https://github.com/SAP/service-fabrik-cli-plugin/blob/master/user_documentation_cf_cli_plugin.md)
User Documentation: [user_documentation_cf_cli_plugin.md](https://github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/blob/master/user_documentation_cf_cli_plugin.md)

## How to obtain support

If you need any support, have any question or have found a bug, please report it in the [GitHub bug tracking system](https://github.com/SAP/service-fabrik-cli-plugin/issues). We shall get back to you.
If you need any support, have any question or have found a bug, please report it in the [GitHub bug tracking system](https://github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/issues). We shall get back to you.

## LICENSE

Expand Down
53 changes: 42 additions & 11 deletions backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"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/SAP/service-fabrik-cli-plugin/constants"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/constants"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/errors"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/guidTranslator"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/helper"
"github.com/cloudfoundry/cli/plugin"
"github.com/fatih/color"
"github.com/olekukonko/tablewriter"
Expand All @@ -29,7 +29,6 @@ func NewBackupCommand(cliConnection plugin.CliConnection) *BackupCommand {
return command
}


func AddColor(text string, textColor color.Attribute) string {
printer := color.New(textColor).Add(color.Bold).SprintFunc()
return printer(text)
Expand Down Expand Up @@ -70,6 +69,16 @@ func getConfiguration() Configuration {
return configuration
}

func GetTimeDifference(initialDate string, finalDate string) int {
initialDate = initialDate[0:19]
format := "2006-01-02 15:04:05"
initialParsedTime, _ := time.Parse(format, initialDate)
finalParsedTime, _ := time.Parse(format, finalDate)
diff := initialParsedTime.Sub(finalParsedTime)
daysDiff := int(diff.Hours() / 24)
return daysDiff
}

func GetHttpClient() *http.Client {
//Skip ssl verification.

Expand Down Expand Up @@ -183,7 +192,6 @@ func (c *BackupCommand) BackupInfo(cliConnection plugin.CliConnection, backupId

}


func (c *BackupCommand) ListBackupsByDeletedInstanceName(cliConnection plugin.CliConnection, serviceInstanceName string) {
fmt.Println("Getting the list of backups in the org", AddColor(helper.GetOrgName(helper.ReadConfigJsonFile()), constants.Cyan), "/ space", AddColor(helper.GetSpaceName(helper.ReadConfigJsonFile()), constants.Cyan), "/ service instance", AddColor(serviceInstanceName, constants.Cyan), "...")

Expand Down Expand Up @@ -256,10 +264,18 @@ func (c *BackupCommand) ListBackupsByDeletedInstanceName(cliConnection plugin.Cl
field[3] = (response[backup].(map[string]interface{}))["trigger"].(string)
field[4] = (response[backup].(map[string]interface{}))["started_at"].(string)
field[5], flag = (response[backup].(map[string]interface{}))["finished_at"].(string)
daysDiff := 0
subTrimmed := field[4][0:19]
finalTrimmed := strings.Replace(subTrimmed, "T", " ", -1)
currentDate := time.Now()
daysDiff = GetTimeDifference(currentDate.String(), finalTrimmed)
if flag == false {
field[5] = "null"
}
table.Append(field)
if daysDiff <= 13 {
table.Append(field)
}

}
}

Expand Down Expand Up @@ -288,10 +304,10 @@ func (c *BackupCommand) ListBackupsByInstance(cliConnection plugin.CliConnection
guid = guidTranslator.FindInstanceGuid(cliConnection, serviceInstanceName, nil, "")
guid = strings.Trim(guid, ",")
guid = strings.Trim(guid, "\"")
fmt.Println("Getting the list of backups in the org", AddColor(helper.GetOrgName(helper.ReadConfigJsonFile()), constants.Cyan), "/ space", AddColor(helper.GetSpaceName(helper.ReadConfigJsonFile()), constants.Cyan), "/ service instance", AddColor(serviceInstanceName, constants.Cyan), "...")
fmt.Println("Getting the list of backups in the org", AddColor(helper.GetOrgName(helper.ReadConfigJsonFile()), constants.Cyan), "/ space", AddColor(helper.GetSpaceName(helper.ReadConfigJsonFile()), constants.Cyan), "/ service instance", AddColor(serviceInstanceName, constants.Cyan), "...")
} else {
guid = instanceGuid
fmt.Println("Getting the list of backups in the org", AddColor(helper.GetOrgName(helper.ReadConfigJsonFile()), constants.Cyan), "/ space", AddColor(helper.GetSpaceName(helper.ReadConfigJsonFile()), constants.Cyan), "/ service instance GUID", AddColor(instanceGuid, constants.Cyan), "...")
fmt.Println("Getting the list of backups in the org", AddColor(helper.GetOrgName(helper.ReadConfigJsonFile()), constants.Cyan), "/ space", AddColor(helper.GetSpaceName(helper.ReadConfigJsonFile()), constants.Cyan), "/ service instance GUID", AddColor(instanceGuid, constants.Cyan), "...")
}
var apiEndpoint string = helper.GetApiEndpoint(helper.ReadConfigJsonFile())
var broker string = GetBrokerName()
Expand Down Expand Up @@ -344,10 +360,17 @@ func (c *BackupCommand) ListBackupsByInstance(cliConnection plugin.CliConnection
field[3] = (response[backup].(map[string]interface{}))["trigger"].(string)
field[4] = (response[backup].(map[string]interface{}))["started_at"].(string)
field[5], flag = (response[backup].(map[string]interface{}))["finished_at"].(string)
daysDiff := 0
subTrimmed := field[4][0:19]
finalTrimmed := strings.Replace(subTrimmed, "T", " ", -1)
currentDate := time.Now()
daysDiff = GetTimeDifference(currentDate.String(), finalTrimmed)
if flag == false {
field[5] = "null"
}
table.Append(field)
if daysDiff <= 13 {
table.Append(field)
}
}

} else {
Expand Down Expand Up @@ -439,19 +462,27 @@ func (c *BackupCommand) ListBackups(cliConnection plugin.CliConnection, noInstan
field[7] = ""
}
}
daysDiff := 0
field[2] = (response[backup].(map[string]interface{}))["username"].(string)
field[3] = (response[backup].(map[string]interface{}))["type"].(string)
field[0] = (response[backup].(map[string]interface{}))["backup_guid"].(string)
field[0] = AddColor(field[0], constants.Cyan)
field[4] = (response[backup].(map[string]interface{}))["trigger"].(string)
field[5] = (response[backup].(map[string]interface{}))["started_at"].(string)
subTrimmed := field[5][0:19]
finalTrimmed := strings.Replace(subTrimmed, "T", " ", -1)
currentDate := time.Now()
daysDiff = GetTimeDifference(currentDate.String(), finalTrimmed)
_, flag := (response[backup].(map[string]interface{}))["finished_at"].(string)
if flag == false {
field[6] = "null"
} else {
field[6] = (response[backup].(map[string]interface{}))["finished_at"].(string)
}
table.Append(field)
if daysDiff <= 13 {
table.Append(field)
}

}
}

Expand Down
4 changes: 2 additions & 2 deletions events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/SAP/service-fabrik-cli-plugin/helper"
"github.com/SAP/service-fabrik-cli-plugin/constants"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/helper"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/constants"
"github.com/cloudfoundry/cli/plugin"
"github.com/fatih/color"
"github.com/olekukonko/tablewriter"
Expand Down
4 changes: 2 additions & 2 deletions guidTranslator/guidTranslator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package guidTranslator

import (
"code.cloudfoundry.org/cli/plugin"
"github.com/SAP/service-fabrik-cli-plugin/errors"
"github.com/SAP/service-fabrik-cli-plugin/helper"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/errors"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/helper"
"strings"
)

Expand Down
2 changes: 1 addition & 1 deletion helper/config-json-parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/SAP/service-fabrik-cli-plugin/errors"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/errors"
"github.com/mitchellh/go-homedir"
"io/ioutil"
"os"
Expand Down
115 changes: 90 additions & 25 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-incubator/service-fabrik-cli-plugin/constants"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/errors"
"github.com/cloudfoundry-incubator/service-fabrik-cli-plugin/guidTranslator"
"github.com/SAP/service-fabrik-cli-plugin/helper"
"github.com/cloudfoundry/cli/plugin"
"github.com/fatih/color"
"github.com/SAP/service-fabrik-cli-plugin/errors"
"github.com/SAP/service-fabrik-cli-plugin/guidTranslator"
"github.com/SAP/service-fabrik-cli-plugin/helper"
"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,22 +98,78 @@ func GetResponse(client *http.Client, req *http.Request) *http.Response {
return resp
}

func (c *RestoreCommand) StartRestore(cliConnection plugin.CliConnection, serviceInstanceName string, backupId string) {
fmt.Println("Starting restore for ", AddColor(serviceInstanceName, cyan), "...")
func GetTrimmedGUID(guid string) (string) {
guid = strings.TrimRight(guid, ",")
guid = strings.Trim(guid, "\"")
return guid
}

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 sourceInstanceId string = ""
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 {
sourceInstanceId = instanceGuid
}
}
if instanceNameOperation == true {
guid := guidTranslator.FindInstanceGuid(cliConnection, instanceName, nil, "")
guid = GetTrimmedGUID(guid)
sourceInstanceId = 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, "\"")
sourceInstanceId = 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 sourceInstanceId != "" {
jsonPrep = `{"time_stamp": "` + epochTime + `", "space_guid": "` + userSpaceGuid + `", "source_instance_id": "` + sourceInstanceId + `"}`
} 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, ",")
guid = strings.Trim(guid, "\"")
guid = GetTrimmedGUID(guid)

var apiEndpoint string = helper.GetApiEndpoint(helper.ReadConfigJsonFile())
var broker string = GetBrokerName()
Expand All @@ -129,12 +187,18 @@ 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])
if len(parts) == 4 {
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 All @@ -152,8 +216,7 @@ func (c *RestoreCommand) AbortRestore(cliConnection plugin.CliConnection, servic
client := GetHttpClient()

var guid string = guidTranslator.FindInstanceGuid(cliConnection, serviceInstanceName, nil, "")
guid = strings.TrimRight(guid, ",")
guid = strings.Trim(guid, "\"")
guid = GetTrimmedGUID(guid)

var userSpaceGuid string = helper.GetSpaceGUID(helper.ReadConfigJsonFile())

Expand All @@ -174,7 +237,9 @@ 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])
if len(parts) == 4 {
fmt.Println("Error - ", parts[3])
}
}

if resp.Status == "202 Accepted" {
Expand Down
Loading