Skip to content

Commit

Permalink
Update WhiskClient.go to use i18n IDs. (#684)
Browse files Browse the repository at this point in the history
* Update WhiskClient.go to use i18n IDs.

* Update WhiskClient.go to use i18n IDs.

* Update WhiskClient.go to use i18n IDs.

* Update WhiskClient.go to use i18n IDs.

* Update WhiskClient.go to use i18n IDs.

* Update WhiskClient.go to use i18n IDs.

* Update WhiskClient.go to use i18n IDs.

* Update WhiskClient.go to use i18n IDs.

* update

* update

* update

* udpate runtimes.go for i18n.

* udpate runtimes.go for i18n.

* udpate servicedeployer.go for i18n.

* udpate servicedeployer.go for i18n.

* udpate servicedeployer.go for i18n.

* udpate servicedeployer.go for i18n.

* udpate servicedeployer.go for i18n.

* udpate servicedeployer.go for i18n.

* udpate servicedeployer.go for i18n.

* Add interactive prompts into whiskclient.go for i18n.

* Add interactive prompts into whiskclient.go for i18n.

* Add interactive prompts into whiskclient.go for i18n.

* Add i18n strings for managed deployments in servicedeployer.go.

* Continue adding i18n support in servicedeployer.go.

* Continue adding i18n support in servicedeployer.go.

* Create reusable method to create/display WhiskClientErrors in servicedeployer.go.

* Create reusable method to display deploy/undeply message in servicedeployer.go.

* Create reusable method to display deploy/undeployed success message in servicedeployer.go.

* Reusable method to perform deploy/undeploy postprocessing in servicedeployer.go
  • Loading branch information
mrutkows authored and Vincent committed Jan 11, 2018
1 parent a519826 commit 150171b
Show file tree
Hide file tree
Showing 8 changed files with 542 additions and 731 deletions.
437 changes: 221 additions & 216 deletions deployers/servicedeployer.go

Large diffs are not rendered by default.

133 changes: 69 additions & 64 deletions deployers/whiskclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ import (
"github.com/apache/incubator-openwhisk-wskdeploy/parsers"
"github.com/apache/incubator-openwhisk-wskdeploy/utils"
"github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
)

const (
COMMANDLINE = "wskdeploy command line"
COMMANDLINE = "wskdeploy command line"
DEFAULTVALUE = "default value"
WSKPROPS = ".wskprops"
WSKPROPS = ".wskprops"
WHISKPROPERTY = "whisk.properties"
INTERINPUT = "interactve input"
INTERINPUT = "interactve input"
)

type PropertyValue struct {
Expand Down Expand Up @@ -67,7 +67,7 @@ var GetCommandLineFlags = func() (string, string, string, string, string) {
return utils.Flags.ApiHost, utils.Flags.Auth, utils.Flags.Namespace, utils.Flags.Key, utils.Flags.Cert
}

var CreateNewClient = func (config_input *whisk.Config) (*whisk.Client, error) {
var CreateNewClient = func(config_input *whisk.Config) (*whisk.Client, error) {
var netClient = &http.Client{
Timeout: time.Second * utils.DEFAULT_HTTP_TIMEOUT,
}
Expand All @@ -85,16 +85,16 @@ func NewWhiskConfig(proppath string, deploymentPath string, manifestPath string,
credential := PropertyValue{}
namespace := PropertyValue{}
apiHost := PropertyValue{}
key := PropertyValue{}
cert := PropertyValue{}
key := PropertyValue{}
cert := PropertyValue{}

// read credentials from command line
apihost, auth, ns, keyfile, certfile := GetCommandLineFlags()
credential = GetPropertyValue(credential, auth, COMMANDLINE)
namespace = GetPropertyValue(namespace, ns, COMMANDLINE)
apiHost = GetPropertyValue(apiHost, apihost, COMMANDLINE)
key = GetPropertyValue(key, keyfile, COMMANDLINE)
cert = GetPropertyValue(cert, certfile, COMMANDLINE)
key = GetPropertyValue(key, keyfile, COMMANDLINE)
cert = GetPropertyValue(cert, certfile, COMMANDLINE)

// now, read them from deployment file if not found on command line
if len(credential.Value) == 0 || len(namespace.Value) == 0 || len(apiHost.Value) == 0 {
Expand Down Expand Up @@ -138,29 +138,33 @@ func NewWhiskConfig(proppath string, deploymentPath string, manifestPath string,
credential = GetPropertyValue(credential, wskprops.AuthKey, WSKPROPS)
namespace = GetPropertyValue(namespace, wskprops.Namespace, WSKPROPS)
apiHost = GetPropertyValue(apiHost, wskprops.APIHost, WSKPROPS)
key = GetPropertyValue(key, wskprops.Key, WSKPROPS)
cert = GetPropertyValue(cert, wskprops.Cert, WSKPROPS)
key = GetPropertyValue(key, wskprops.Key, WSKPROPS)
cert = GetPropertyValue(cert, wskprops.Cert, WSKPROPS)

// TODO() see if we can split the following whisk prop logic into a separate function
// now, read credentials from whisk.properties but this is only acceptable within Travis
// whisk.properties will soon be deprecated and should not be used for any production deployment
whiskproperty, _ := GetWskPropFromWhiskProperty(pi)

var warnmsg string

credential = GetPropertyValue(credential, whiskproperty.AuthKey, WHISKPROPERTY)
if credential.Source == WHISKPROPERTY {
// TODO() i18n
wskprint.PrintlnOpenWhiskWarning("The authentication key was retrieved from whisk.properties " +
"which will soon be deprecated please do not use it outside of Travis builds.")
warnmsg = wski18n.T(wski18n.ID_WARN_WHISK_PROPS_DEPRECATED,
map[string]interface{}{"key": "authenticaton key"})
wskprint.PrintlnOpenWhiskWarning(warnmsg)
}
namespace = GetPropertyValue(namespace, whiskproperty.Namespace, WHISKPROPERTY)
if namespace.Source == WHISKPROPERTY {
// TODO() i18n
wskprint.PrintlnOpenWhiskWarning("The namespace was retrieved from whisk.properties " +
"which will soon be deprecated please do not use it outside of Travis builds.")
warnmsg = wski18n.T(wski18n.ID_WARN_WHISK_PROPS_DEPRECATED,
map[string]interface{}{"key": "namespace"})
wskprint.PrintlnOpenWhiskWarning(warnmsg)
}
apiHost = GetPropertyValue(apiHost, whiskproperty.APIHost, WHISKPROPERTY)
if apiHost.Source == WHISKPROPERTY {
// TODO() i18n
wskprint.PrintlnOpenWhiskWarning("The API host was retrieved from whisk.properties " +
"which will soon be deprecated please do not use it outside of Travis builds.")
warnmsg = wski18n.T(wski18n.ID_WARN_WHISK_PROPS_DEPRECATED,
map[string]interface{}{"key": "API host"})
wskprint.PrintlnOpenWhiskWarning(warnmsg)
}

// set namespace to default namespace if not yet found
Expand All @@ -169,98 +173,99 @@ func NewWhiskConfig(proppath string, deploymentPath string, manifestPath string,
namespace.Source = DEFAULTVALUE
}

// TODO() See if we can split off the interactive logic into a separate function
// If we still can not find the values we need, check if it is interactive mode.
// If so, we prompt users for the input.
// The namespace is set to a default value at this point if not provided.
if len(apiHost.Value) == 0 && isInteractive == true {
// TODO() i18n
host := promptForValue("\nPlease provide the hostname for OpenWhisk [default value is openwhisk.ng.bluemix.net]: ")
host := promptForValue(wski18n.T(wski18n.ID_MSG_PROMPT_APIHOST))
if host == "" {
// TODO() tell caller that we are using this default, look to make a const at top of file
// TODO() programmatically tell caller that we are using this default
// TODO() make this configurable or remove
host = "openwhisk.ng.bluemix.net"
}
apiHost.Value = host
apiHost.Source = INTERINPUT
}

if len(credential.Value) == 0 && isInteractive == true {
// TODO() i18n
cred := promptForValue("\nPlease provide an authentication token: ")
cred := promptForValue(wski18n.T(wski18n.ID_MSG_PROMPT_AUTHKEY))
credential.Value = cred
credential.Source = INTERINPUT

// The namespace is always associated with the credential. Both of them should be picked up from the same source.
if len(namespace.Value) == 0 || namespace.Value == whisk.DEFAULT_NAMESPACE {
// TODO() i18n
ns := promptForValue("\nPlease provide a namespace [default value is guest]: ")
tempNamespace := promptForValue(wski18n.T(wski18n.ID_MSG_PROMPT_NAMESPACE))
source := INTERINPUT

if ns == "" {
ns = whisk.DEFAULT_NAMESPACE
if tempNamespace == "" {
tempNamespace = whisk.DEFAULT_NAMESPACE
source = DEFAULTVALUE
}

namespace.Value = ns
namespace.Value = tempNamespace
namespace.Source = source
}
}

mode := true
if (len(cert.Value) != 0 && len(key.Value) != 0) {
mode = false
}
mode := true
if (len(cert.Value) != 0 && len(key.Value) != 0) {
mode = false
}

clientConfig = &whisk.Config {
clientConfig = &whisk.Config{
AuthToken: credential.Value, //Authtoken
Namespace: namespace.Value, //Namespace
Namespace: namespace.Value, //Namespace
Host: apiHost.Value,
Version: "v1",
Cert: cert.Value,
Key: key.Value,
Cert: cert.Value,
Key: key.Value,
Insecure: mode, // true if you want to ignore certificate signing
}

// validate we have credential, apihost and namespace
err := validateClientConfig(credential, apiHost, namespace)

return clientConfig, err
}

func validateClientConfig(credential PropertyValue, apiHost PropertyValue, namespace PropertyValue) (error) {

// Display error message based upon which config value was missing
if len(credential.Value) == 0 || len(apiHost.Value) == 0 || len(namespace.Value) == 0 {
var errStr string
var errmsg string
if len(credential.Value) == 0 {
errStr += wski18n.T("The authentication key is not configured.\n")
} else {
errStr += wski18n.T("The authenitcation key is set from {{.authsource}}.\n",
map[string]interface{}{"authsource": credential.Source})
errmsg = wski18n.T(wski18n.ID_MSG_CONFIG_MISSING_AUTHKEY)
}

if len(apiHost.Value) == 0 {
errStr += wski18n.T("The API host is not configured.\n")
} else {
errStr += wski18n.T("The API host is {{.apihost}}, from {{.apisource}}.\n",
map[string]interface{}{"apihost": apiHost.Value, "apisource": apiHost.Source})
errmsg = wski18n.T(wski18n.ID_MSG_CONFIG_MISSING_APIHOST)
}

if len(namespace.Value) == 0 {
errStr += wski18n.T("The namespace is not configured.\n")
} else {
errStr += wski18n.T("The namespace is {{.namespace}}, from {{.namespacesource}}.\n",
map[string]interface{}{"namespace": namespace.Value, "namespacesource": namespace.Source})

errmsg = wski18n.T(wski18n.ID_MSG_CONFIG_MISSING_NAMESPACE)
}
whisk.Debug(whisk.DbgError, errStr)
return clientConfig, wskderrors.NewWhiskClientInvalidConfigError(errStr)

return wskderrors.NewWhiskClientInvalidConfigError(errmsg)
}

stdout := wski18n.T("The API host is {{.apihost}}, from {{.apisource}}.\n",
map[string]interface{}{"apihost": apiHost.Value, "apisource": apiHost.Source})
whisk.Debug(whisk.DbgInfo, stdout)
// Show caller what final values we used for credential, apihost and namespace
stdout := wski18n.T(wski18n.ID_MSG_CONFIG_INFO_APIHOST_X_host_X_source_X,
map[string]interface{}{"host": apiHost.Value, "source": apiHost.Source})
wskprint.PrintOpenWhiskStatus(stdout)

stdout = wski18n.T(wski18n.ID_MSG_CONFIG_INFO_AUTHKEY_X_source_X,
map[string]interface{}{"source": credential.Source})
wskprint.PrintOpenWhiskStatus(stdout)

stdout = wski18n.T("The auth key is set, from {{.authsource}}.\n",
map[string]interface{}{"authsource": credential.Source})
whisk.Debug(whisk.DbgInfo, stdout)
stdout = wski18n.T(wski18n.ID_MSG_CONFIG_INFO_NAMESPACE_X_namespace_X_source_X,
map[string]interface{}{"namespace": namespace.Value, "source": namespace.Source})
wskprint.PrintOpenWhiskStatus(stdout)

stdout = wski18n.T("The namespace is {{.namespace}}, from {{.namespacesource}}.\n",
map[string]interface{}{"namespace": namespace.Value, "namespacesource": namespace.Source})
whisk.Debug(whisk.DbgInfo, stdout)
return clientConfig, nil
return nil
}

// TODO() move into its own package "wskread" and add support for passing in default value
var promptForValue = func(msg string) (string) {
reader := bufio.NewReader(os.Stdin)
fmt.Print(msg)
Expand Down
9 changes: 6 additions & 3 deletions utils/runtimes.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ var DefaultRunTimes map[string]string
// `curl -k https://openwhisk.ng.bluemix.net`
// hard coding it here in case of network unavailable or failure.
func ParseOpenWhisk(apiHost string) (op OpenWhiskInfo, err error) {
// TODO() create HTTP header constants and use them
ct := "application/json; charset=UTF-8"
req, _ := http.NewRequest("GET", "https://"+apiHost, nil)
req.Header.Set("Content-Type", ct)
Expand All @@ -92,7 +93,8 @@ func ParseOpenWhisk(apiHost string) (op OpenWhiskInfo, err error) {

res, err := netClient.Do(req)
if err != nil {
errString := wski18n.T("Failed to get the supported runtimes from OpenWhisk service: {{.err}}.\n",
// TODO() create an error
errString := wski18n.T(wski18n.ID_ERR_GET_RUNTIMES_X_err_X,
map[string]interface{}{"err": err.Error()})
whisk.Debug(whisk.DbgWarn, errString)
}
Expand All @@ -102,14 +104,15 @@ func ParseOpenWhisk(apiHost string) (op OpenWhiskInfo, err error) {
}

// Local openwhisk deployment sometimes only returns "application/json" as the content type
// TODO() create HTTP header constants and use them
if err != nil || !strings.Contains(ct, res.Header.Get("Content-Type")) {
stdout := wski18n.T("Start to unmarshal Openwhisk info from local values.\n")
stdout := wski18n.T(wski18n.ID_MSG_UNMARSHAL_LOCAL)
whisk.Debug(whisk.DbgInfo, stdout)
err = json.Unmarshal(RUNTIME_DETAILS, &op)
} else {
b, _ := ioutil.ReadAll(res.Body)
if b != nil && len(b) > 0 {
stdout := wski18n.T("Unmarshal Openwhisk info from internet.\n")
stdout := wski18n.T(wski18n.ID_MSG_UNMARSHAL_NETWORK)
whisk.Debug(whisk.DbgInfo, stdout)
err = json.Unmarshal(b, &op)
}
Expand Down
4 changes: 4 additions & 0 deletions wskderrors/wskdeployerror.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ func (e *WskDeployBaseErr) SetMessage(message interface{}) {
}
}

func (e *WskDeployBaseErr) AppendDetail(detail string){
e.appendDetail(detail)
}

func (e *WskDeployBaseErr) appendDetail(detail string){
fmt := fmt.Sprintf("\n%s %s", STR_INDENT_1, detail)
e.Message = e.Message + fmt
Expand Down
Loading

0 comments on commit 150171b

Please sign in to comment.