Skip to content

Commit

Permalink
Merge pull request #327 from cloudfoundry-community/dev
Browse files Browse the repository at this point in the history
Prepare version v0.14.0
  • Loading branch information
ArthurHlt authored Mar 29, 2021
2 parents f82734d + 77d9a37 commit c8a7f68
Show file tree
Hide file tree
Showing 14 changed files with 226 additions and 29 deletions.
7 changes: 6 additions & 1 deletion cloudfoundry/common/polling.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@ func Polling(pollingFunc func() (bool, error), waitTime time.Duration) error {

func PollingWithTimeout(pollingFunc func() (bool, error), waitTime time.Duration, timeout time.Duration) error {
stagingStartTime := time.Now()
var previousErr error = nil
for {
if time.Since(stagingStartTime) > timeout {
if previousErr != nil {
return fmt.Errorf("Timeout of %s reached with a previous error given: %s", timeout, previousErr.Error())
}
return fmt.Errorf("Timeout of %s reached", timeout)
}
finished, err := pollingFunc()
if err != nil {
if err != nil && finished {
return err
}
previousErr = err
if finished {
break
}
Expand Down
3 changes: 3 additions & 0 deletions cloudfoundry/managers/appdeployers/runbinder.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ func (r RunBinder) WaitStart(appDeploy AppDeploy) error {
if instance.State == constant.ApplicationInstanceRunning {
return true, nil
}
if instance.State == constant.ApplicationInstanceDown {
return false, fmt.Errorf("Instance %d failed with state %s for app %s", i, instance.State, appDeploy.App.Name)
}
return true, fmt.Errorf("Instance %d failed with state %s for app %s", i, instance.State, appDeploy.App.Name)
}

Expand Down
7 changes: 5 additions & 2 deletions cloudfoundry/managers/bits/bitsmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func (m BitsManager) CopyApp(origAppGuid string, newAppGuid string) error {
if err != nil {
return err
}
defer resp.Body.Close()
var j job
err = json.NewDecoder(resp.Body).Decode(&j)
if err != nil {
Expand Down Expand Up @@ -123,10 +124,11 @@ func (m BitsManager) UploadBuildpack(buildpackGUID string, bpPath string) error
req.ContentLength = m.predictPartBuildpack(baseName, fileSize, mpw.Boundary())
req.Body = r

_, err = m.rawClient.Do(req)
resp, err := m.rawClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
return nil
}

Expand Down Expand Up @@ -181,10 +183,11 @@ func (m BitsManager) UploadApp(appGUID string, path string) error {
req.ContentLength = m.predictPartApp(fileSize, mpw.Boundary())
req.Body = r

_, err = m.rawClient.Do(req)
resp, err := m.rawClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
return nil
}

Expand Down
8 changes: 5 additions & 3 deletions cloudfoundry/metadata.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package cloudfoundry

import (
"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
"encoding/json"
"fmt"
"io/ioutil"

"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
"github.com/blang/semver"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers"
"io/ioutil"
)

type metadataType string
Expand Down Expand Up @@ -96,7 +97,8 @@ func resourceToPayload(d *schema.ResourceData, key string) map[string]*string {

// 1.
for key, val := range newV {
res[key] = &val
v := val
res[key] = &v
}

// 2.
Expand Down
24 changes: 14 additions & 10 deletions cloudfoundry/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,26 +490,24 @@ func assertHTTPResponse(url string, expectedStatusCode int, expectedResponses *[
var finalErr error
// this assert is used to get on a route from gorouter
// delay and retry is necessary in case of the route not yet registered in gorouter
for i := 0; i < 9; i++ {
fn := func(url string, expectedStatusCode int, expectedResponses *[]string) error {
finalErr = nil
time.Sleep(1 * time.Second)
resp, err := client.Get(url)
if err != nil {
finalErr = err
continue
return err
}
defer resp.Body.Close()
if expectedStatusCode != resp.StatusCode {
finalErr = fmt.Errorf(
return fmt.Errorf(
"expected response status code from url '%s' to be '%d', but actual was: %s",
url, expectedStatusCode, resp.Status)
continue
}
if expectedResponses != nil {
in := resp.Body
out := bytes.NewBuffer(nil)
if _, err = io.Copy(out, in); err != nil {
finalErr = err
continue
return err
}
content := out.String()

Expand All @@ -521,17 +519,23 @@ func assertHTTPResponse(url string, expectedStatusCode int, expectedResponses *[
}
}
if !found {
finalErr = fmt.Errorf(
return fmt.Errorf(
"expected response from url '%s' to be one of '%v', but actual was '%s'",
url, *expectedResponses, content)
continue
}
}
return nil
}
for i := 0; i < 9; i++ {
err := fn(url, expectedStatusCode, expectedResponses)
if err != nil {
finalErr = err
continue
}
}

return finalErr
}

func TestMain(m *testing.M) {
fmt.Println("Running pre-hook...")
// defer and os.Exit are not friends :(
Expand Down
32 changes: 31 additions & 1 deletion cloudfoundry/resource_cf_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func resourceApp() *schema.Resource {
Importer: &schema.ResourceImporter{
State: resourceAppImport,
},
SchemaVersion: 3,
SchemaVersion: 4,
MigrateState: resourceAppMigrateState,
Schema: map[string]*schema.Schema{

Expand Down Expand Up @@ -318,6 +318,7 @@ func resourceAppRead(d *schema.ResourceData, meta interface{}) error {
if err != nil {
return err
}
bindings = reorderBindings(bindings, d.Get("service_binding").([]interface{}))
AppDeployToResourceData(d, appdeployers.AppDeployResponse{
App: app,
RouteMapping: mappings,
Expand All @@ -330,6 +331,35 @@ func resourceAppRead(d *schema.ResourceData, meta interface{}) error {
return nil
}

func getServiceBindingFromList(guid string, bindings []ccv2.ServiceBinding) (ccv2.ServiceBinding, bool) {
for _, binding := range bindings {
if binding.ServiceInstanceGUID == guid {
return binding, true
}
}
return ccv2.ServiceBinding{}, false
}

func reorderBindings(bindings []ccv2.ServiceBinding, currentBindings []interface{}) []ccv2.ServiceBinding {
finalBindings := make([]ccv2.ServiceBinding, 0)
for _, currentBindings := range currentBindings {
if currentBindings == nil {
continue
}
item := currentBindings.(map[string]interface{})
if binding, ok := getServiceBindingFromList(item["service_instance"].(string), bindings); ok {
finalBindings = append(finalBindings, binding)
}
}
for _, binding := range bindings {
if _, ok := getServiceBindingFromList(binding.ServiceInstanceGUID, finalBindings); ok {
continue
}
finalBindings = append(finalBindings, binding)
}
return finalBindings
}

func resourceAppUpdate(d *schema.ResourceData, meta interface{}) error {
d.Partial(true)
d.SetPartial("docker_credentials")
Expand Down
70 changes: 70 additions & 0 deletions cloudfoundry/resource_cf_app_migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,81 @@ func resourceAppMigrateState(
case 2:
log.Println("[INFO] Found app Record State v2; migrating from v2 to v3")
return migrateAppStateV2toV3(is, meta)
case 3:
log.Println("[INFO] Found app Record State v3; migrating from v3 to v4")
return migrateAppStateV3toV4(is, meta)
default:
return is, fmt.Errorf("Unexpected schema version: %d", v)
}
}

func migrateAppStateV3toV4(is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
oldSchema := map[string]*schema.Schema{
"service_binding": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Set: func(v interface{}) int {
elem := v.(map[string]interface{})
return hashcode.String(elem["service_instance"].(string))
},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"service_instance": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"params": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
},
"binding_id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
},
},
}

reader := &schema.MapFieldReader{
Schema: oldSchema,
Map: schema.BasicMapReader(is.Attributes),
}
result, err := reader.ReadField([]string{"service_binding"})
if err != nil {
return is, err
}
bindings := make([]map[string]interface{}, 0)
result, err = reader.ReadField([]string{"service_binding"})
if err == nil && result.Exists {
oldBindings := getListOfStructs(result.Value)
for _, b := range oldBindings {
bindings = append(bindings, map[string]interface{}{
"service_instance": b["service_instance"],
"params": b["params"],
"params_json": b["params_json"],
})
}
}

is.Attributes = cleanByKeyAttribute("service_binding", is.Attributes)

writer := schema.MapFieldWriter{
Schema: resourceApp().Schema,
}

err = writer.WriteField([]string{"service_binding"}, bindings)
if err != nil {
return is, err
}
attr := is.Attributes
for k, v := range writer.Map() {
attr[k] = v
}
is.Attributes = attr
return is, nil
}

func migrateAppStateV2toV3(is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
if is.Empty() {
log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
Expand Down
1 change: 1 addition & 0 deletions cloudfoundry/resource_cf_route_service_binding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ func checkAppResponse(url string, code int) resource.TestCheckFunc {
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != code {
// on cf without valid certif it has 502 error
if resp.StatusCode == 502 {
Expand Down
33 changes: 32 additions & 1 deletion cloudfoundry/resource_cf_service_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"

"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
Expand All @@ -24,6 +25,10 @@ func resourceServiceInstance() *schema.Resource {
Update: resourceServiceInstanceUpdate,
Delete: resourceServiceInstanceDelete,

SchemaVersion: 1,

MigrateState: resourceServiceInstanceMigrateState,

Importer: &schema.ResourceImporter{
State: resourceServiceInstanceImport,
},
Expand All @@ -35,7 +40,6 @@ func resourceServiceInstance() *schema.Resource {
},

Schema: map[string]*schema.Schema{

"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Expand All @@ -55,6 +59,16 @@ func resourceServiceInstance() *schema.Resource {
Default: "",
ValidateFunc: validation.StringIsJSON,
},
"replace_on_service_plan_change": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"replace_on_params_change": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"tags": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Expand All @@ -66,6 +80,23 @@ func resourceServiceInstance() *schema.Resource {
Default: false,
},
},
CustomizeDiff: customdiff.All(
customdiff.ForceNewIf(
"service_plan", func(d *schema.ResourceDiff, meta interface{}) bool {
if ok := d.Get("replace_on_service_plan_change").(bool); ok {
return true
}
return false
}),
customdiff.ForceNewIf(
"params", func(d *schema.ResourceDiff, meta interface{}) bool {
if ok := d.Get("replace_on_params_change").(bool); ok {
return true
}
return false
},
),
),
}
}

Expand Down
Loading

0 comments on commit c8a7f68

Please sign in to comment.