Skip to content

Commit

Permalink
Merge pull request #231 from cloudfoundry-community/dev
Browse files Browse the repository at this point in the history
Prepare for v0.11.0
  • Loading branch information
ArthurHlt authored Jan 29, 2020
2 parents bf7d0e6 + a08c6b7 commit 7a40ecf
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 62 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: go
go:
- '1.12'
- '1.13'
stages:
- testlint
- testds
Expand Down
3 changes: 3 additions & 0 deletions cloudfoundry/managers/appdeployers/bluegreenv2_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ func (s BlueGreenV2) Restage(appDeploy AppDeploy) (AppDeployResponse, error) {
},
{
Forward: func(ctx Context) (Context, error) {
if appDeploy.App.DockerImage != "" {
return ctx, nil
}
appResp := ctx["app_response"].(AppDeployResponse)
err := s.bitsManager.CopyApp(appDeploy.App.GUID, appResp.App.GUID)
return ctx, err
Expand Down
2 changes: 2 additions & 0 deletions cloudfoundry/managers/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type Config struct {
Endpoint string
User string
Password string
SSOPasscode string
CFClientID string
CFClientSecret string
UaaClientID string
Expand All @@ -13,4 +14,5 @@ type Config struct {
AppLogsMax int
PurgeWhenDelete bool
DefaultQuotaName string
StoreTokensPath string
}
98 changes: 81 additions & 17 deletions cloudfoundry/managers/session.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
package managers

import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"strings"
"time"

"code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1"
netWrapper "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper"
"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
Expand All @@ -14,17 +24,10 @@ import (
uaaWrapper "code.cloudfoundry.org/cli/api/uaa/wrapper"
"code.cloudfoundry.org/cli/command/translatableerror"
"code.cloudfoundry.org/cli/util/configv3"
"crypto/tls"
"fmt"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers/appdeployers"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers/bits"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers/noaa"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers/raw"
"net"
"net/http"
"os"
"strings"
"time"
)

// Session - wraps the available clients from CF cli
Expand Down Expand Up @@ -66,6 +69,15 @@ type Session struct {
ApiEndpoint string
}

type CFTokens struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
}

func (t CFTokens) IsSet() bool {
return t.AccessToken != ""
}

// NewSession -
func NewSession(c Config) (s *Session, err error) {
if c.User == "" && c.CFClientID == "" {
Expand Down Expand Up @@ -197,30 +209,50 @@ func (s *Session) init(config *configv3.Config, configUaa *configv3.Config, conf
}

// -------------------------
// try connecting with pair given on uaa to retrieve access token and refresh token
// Obtain access and refresh tokens
var accessToken string
var refreshToken string
if config.CFUsername() != "" {
var errType string

tokFromStore := s.loadTokFromStoreIfNeed(configSess.StoreTokensPath, uaaClient.RefreshAccessToken)
if tokFromStore.IsSet() {
accessToken = tokFromStore.AccessToken
refreshToken = tokFromStore.RefreshToken
} else if configSess.SSOPasscode != "" {
// try connecting with SSO passcode to retrieve access token and refresh token
accessToken, refreshToken, err = uaaClient.Authenticate(map[string]string{
"passcode": configSess.SSOPasscode,
}, "", constant.GrantTypePassword)
errType = "SSO passcode"
} else if config.CFUsername() != "" {
// try connecting with pair given on uaa to retrieve access token and refresh token
accessToken, refreshToken, err = uaaClient.Authenticate(map[string]string{
"username": config.CFUsername(),
"password": config.CFPassword(),
}, "", constant.GrantTypePassword)
errType = "username/password"
} else if config.UAAOAuthClient() != "cf" {
accessToken, refreshToken, err = uaaClient.Authenticate(map[string]string{
"client_id": config.UAAOAuthClient(),
"client_secret": config.UAAOAuthClientSecret(),
}, "", constant.GrantTypeClientCredentials)
errType = "client_id/client_secret"
}
if err != nil {
return fmt.Errorf("Error when authenticate on cf: %s", err)
return fmt.Errorf("Error when authenticate on cf using %s: %s", errType, err)
}
if accessToken == "" {
return fmt.Errorf("A pair of username/password or a pair of client_id/client_secret muste be set.")
return fmt.Errorf("A pair of username/password, a pair of client_id/client_secret, or a SSO passcode must be set.")
}

config.SetAccessToken(fmt.Sprintf("bearer %s", accessToken))
config.SetRefreshToken(refreshToken)

// Write access and refresh tokens to file if needed
err = s.saveTokToStoreIfNeed(configSess.StoreTokensPath, accessToken, refreshToken)
if err != nil {
return fmt.Errorf("Error when trying to save tokens to %s: %s", configSess.StoreTokensPath, err.Error())
}
// -------------------------
// assign uaa client to request wrappers
uaaAuthWrapper.SetClient(uaaClient)
Expand Down Expand Up @@ -249,10 +281,8 @@ func (s *Session) init(config *configv3.Config, configUaa *configv3.Config, conf
var accessTokenSess string
var refreshTokenSess string
if configUaa.UAAOAuthClient() == "cf" {
accessTokenSess, refreshTokenSess, err = uaaClientSess.Authenticate(map[string]string{
"username": config.CFUsername(),
"password": config.CFPassword(),
}, "", constant.GrantTypePassword)
accessTokenSess = accessToken
refreshTokenSess = refreshToken
} else {
accessTokenSess, refreshTokenSess, err = uaaClientSess.Authenticate(map[string]string{
"client_id": configUaa.UAAOAuthClient(),
Expand All @@ -261,10 +291,10 @@ func (s *Session) init(config *configv3.Config, configUaa *configv3.Config, conf
}

if err != nil {
return fmt.Errorf("Error when authenticate on uaa: %s", err)
return fmt.Errorf("Error when authenticate on uaa [%s]: %s", configUaa.UAAOAuthClient(), err)
}
if accessTokenSess == "" {
return fmt.Errorf("A pair of pair of uaa_client_id/uaa_client_secret muste be set.")
return fmt.Errorf("A pair of pair of uaa_client_id/uaa_client_secret must be set.")
}
configUaa.SetAccessToken(fmt.Sprintf("bearer %s", accessTokenSess))
configUaa.SetRefreshToken(refreshTokenSess)
Expand Down Expand Up @@ -376,6 +406,40 @@ func (s *Session) loadDefaultQuotaGuid(quotaName string) error {
return nil
}

func (s *Session) loadTokFromStoreIfNeed(storePath string, refresher func(refreshToken string) (uaa.RefreshedTokens, error)) CFTokens {
if storePath == "" {
return CFTokens{}
}
b, err := ioutil.ReadFile(storePath)
if err != nil {
return CFTokens{}
}
var tokens CFTokens
err = json.Unmarshal(b, &tokens)
if err != nil {
return CFTokens{}
}
refreshed, err := refresher(tokens.RefreshToken)
if err != nil {
return CFTokens{}
}
return CFTokens{
AccessToken: refreshed.AccessToken,
RefreshToken: refreshed.RefreshToken,
}
}

func (s *Session) saveTokToStoreIfNeed(storePath, accessToken, refreshToken string) error {
if storePath == "" {
return nil
}
b, _ := json.MarshalIndent(CFTokens{
AccessToken: accessToken,
RefreshToken: refreshToken,
}, "", " ")
return ioutil.WriteFile(storePath, b, 0644)
}

// IsDefaultGroup -
func (s *Session) DefaultQuotaGuid() string {
return s.defaultQuotaGuid
Expand Down
13 changes: 13 additions & 0 deletions cloudfoundry/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ func Provider() terraform.ResourceProvider {
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("CF_PASSWORD", ""),
},
"sso_passcode": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("CF_SSO_PASSCODE", ""),
},
"cf_client_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -71,6 +76,12 @@ func Provider() terraform.ResourceProvider {
DefaultFunc: schema.EnvDefaultFunc("CF_PURGE_WHEN_DELETE", false),
Description: "Set to true to purge when deleting a resource (e.g.: service instance, service broker)",
},
"store_tokens_path": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("CF_STORE_TOKENS_PATH", ""),
Description: "Path to a file to store tokens used for login. (this is useful for sso, this avoid requiring each time sso passcode)",
},
},

DataSourcesMap: map[string]*schema.Resource{
Expand Down Expand Up @@ -129,13 +140,15 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
Endpoint: strings.TrimSuffix(d.Get("api_url").(string), "/"),
User: d.Get("user").(string),
Password: d.Get("password").(string),
SSOPasscode: d.Get("sso_passcode").(string),
CFClientID: d.Get("cf_client_id").(string),
CFClientSecret: d.Get("cf_client_secret").(string),
UaaClientID: d.Get("uaa_client_id").(string),
UaaClientSecret: d.Get("uaa_client_secret").(string),
SkipSslValidation: d.Get("skip_ssl_validation").(bool),
AppLogsMax: d.Get("app_logs_max").(int),
DefaultQuotaName: d.Get("default_quota_name").(string),
StoreTokensPath: d.Get("store_tokens_path").(string),
}
return managers.NewSession(c)
}
19 changes: 12 additions & 7 deletions cloudfoundry/resource_cf_app.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package cloudfoundry

import (
"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
"encoding/json"
"fmt"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers/appdeployers"
"log"
"reflect"
"strings"
"time"

"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers"
"github.com/terraform-providers/terraform-provider-cloudfoundry/cloudfoundry/managers/appdeployers"

"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)
Expand Down Expand Up @@ -444,8 +445,12 @@ func resourceAppUpdate(d *schema.ResourceData, meta interface{}) error {
if d.HasChange("enable_ssh") {
appUpdate.EnableSSH = BoolToNullBool(d.Get("enable_ssh").(bool))
}
if d.HasChange("stopped") && !d.Get("stopped").(bool) {
appUpdate.State = constant.ApplicationStopped
if d.HasChange("stopped") {
state := constant.ApplicationStarted
if d.Get("stopped").(bool) {
state = constant.ApplicationStopped
}
appUpdate.State = state
}
if d.HasChange("docker_image") {
appUpdate.DockerImage = d.Get("docker_image").(string)
Expand Down
6 changes: 6 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ The following arguments are supported:
* `password` - (Optional) Cloud Foundry user's password. This can also be specified
with the `CF_PASSWORD` shell environment variable.

* `sso_passcode` - (Optional) A passcode provided by UAA single sign on. The equivalent of `cf login --sso-passcode`. This can also be specified
with the `CF_SSO_PASSCODE` shell environment variable.

* `cf_client_id` - (Optional) The cf client ID to make request with a client instead of user. This can also be specified
with the `CF_CLIENT_ID` shell environment variable.

Expand All @@ -73,3 +76,6 @@ The following arguments are supported:

* `purge_when_delete` - (Optional) Set to true to purge when deleting a resource (e.g.: service instance, service broker) . This can also be specified
with the `CF_PURGE_WHEN_DELETE` shell environment variable.

* `store_tokens_path` - (Optional) Path to a file to store tokens used for login. (this is useful for sso, this avoid
requiring each time sso passcode) . This can also be specified with the `CF_STORE_TOKENS_PATH` shell environment variable.
13 changes: 2 additions & 11 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module github.com/terraform-providers/terraform-provider-cloudfoundry

go 1.12
go 1.13

replace code.cloudfoundry.org/cli => github.com/cloudfoundry-community/cloudfoundry-cli v0.0.1-complete-api
replace code.cloudfoundry.org/cli => github.com/cloudfoundry-community/cloudfoundry-cli v0.0.2-complete-api

require (
code.cloudfoundry.org/bytefmt v0.0.0-20180906201452-2aa6f33b730c // indirect
Expand Down Expand Up @@ -34,19 +34,10 @@ require (
github.com/hashicorp/terraform v0.12.0
github.com/lunixbochs/vtclean v1.0.0 // indirect
github.com/mailru/easyjson v0.0.0-20190403194419-1ea4449da983 // indirect
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/onsi/ginkgo v1.10.1 // indirect
github.com/onsi/gomega v1.7.0 // indirect
github.com/poy/eachers v0.0.0-20181020210610-23942921fe77 // indirect
github.com/satori/go.uuid v1.2.0
github.com/sirupsen/logrus v1.4.2 // indirect
github.com/stretchr/testify v1.4.0 // indirect
github.com/tedsuo/rata v1.0.0 // indirect
github.com/vito/go-interact v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 // indirect
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 // indirect
google.golang.org/grpc v1.21.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.2.4 // indirect
)
Loading

0 comments on commit 7a40ecf

Please sign in to comment.