22
22
const conductor = require ( './conductor' )
23
23
const fs = require ( 'fs' )
24
24
const openwhisk = require ( 'openwhisk' )
25
+ const ibmcloudUtils = require ( './ibmcloud-utils' )
25
26
const os = require ( 'os' )
26
27
const path = require ( 'path' )
27
28
29
+ const NS_TYPE_CF = 'CF'
30
+ const NS_TYPE_IAM = 'IAM'
31
+
28
32
// return enhanced openwhisk client capable of deploying compositions
29
33
module . exports = function ( options , basic , bearer ) {
30
34
// try to extract apihost and key first from whisk property file file and then from process.env
31
35
let apihost
32
36
let apiversion
33
37
let apikey
34
38
let ignorecerts
35
- let namespace = '_'
39
+ let namespace = ibmcloudUtils . getNamespaceId ( )
36
40
let token
37
41
let authHandler
38
42
@@ -49,31 +53,77 @@ module.exports = function (options, basic, bearer) {
49
53
apiversion = parts [ 1 ]
50
54
} else if ( parts [ 0 ] === 'AUTH' ) {
51
55
apikey = parts [ 1 ]
52
- } else if ( parts [ 0 ] === 'NAMESPACE' ) {
53
- namespace = parts [ 1 ]
54
56
} else if ( parts [ 0 ] === 'APIGW_ACCESS_TOKEN' ) {
55
57
token = parts [ 1 ]
56
58
}
57
59
}
58
60
}
59
- } catch ( error ) { }
61
+ } catch ( error ) { }
60
62
61
63
if ( process . env . __OW_API_HOST ) apihost = process . env . __OW_API_HOST
62
64
if ( process . env . __OW_API_KEY ) apikey = process . env . __OW_API_KEY
63
65
if ( process . env . __OW_NAMESPACE ) namespace = process . env . __OW_NAMESPACE
64
66
if ( process . env . __OW_IGNORE_CERTS ) ignorecerts = process . env . __OW_IGNORE_CERTS
65
67
if ( process . env . __OW_APIGW_TOKEN ) token = process . env . __OW_APIGW_TOKEN
66
68
67
- if ( bearer || ( ! basic && namespace !== '_' ) ) {
68
- // switch from basic auth to bearer token
69
+ // check whether there is a CLI argument that overrides the API key retrieved from the config or env
70
+ if ( options && options . api_key ) apikey = options . api_key
71
+
72
+ // retrieve the namespace type
73
+ // we need to apply different authentication strategies for CF and IAM
74
+ const namespaceType = ibmcloudUtils . getNamespaceType ( )
75
+
76
+ //
77
+ // check for IAM-based namespaces, first
78
+ if ( namespaceType === NS_TYPE_IAM ) {
79
+ // for authentication, we'll use the user IAM access token
80
+ const iamToken = ibmcloudUtils . getIamAuthHeader ( )
81
+
82
+ // define an appropriate authentication handler for IAM
69
83
authHandler = {
70
84
getAuthHeader : ( ) => {
71
- return Promise . resolve ( `Bearer ${ token } ` )
85
+ // use bearer token for IAM authentication
86
+ return Promise . resolve ( iamToken )
72
87
}
73
88
}
89
+
90
+ // ignore the API key value, in case of an IAM-based namespace
91
+ apikey = undefined
92
+
93
+ //
94
+ // in case of CF-based namespaces, the user can opt-in for using bearer token authentication instead of using the default basic authentication
95
+ } else if ( namespaceType === NS_TYPE_CF ) {
96
+ if ( bearer && ! basic ) {
97
+ // switch from basic auth to bearer token
98
+ authHandler = {
99
+ getAuthHeader : ( ) => {
100
+ return Promise . resolve ( `Bearer ${ token } ` )
101
+ }
102
+ }
103
+ } else if ( apikey ) {
104
+ // use basic auth
105
+ authHandler = {
106
+ getAuthHeader : ( ) => {
107
+ const apiKeyBase64 = Buffer . from ( apikey ) . toString ( 'base64' )
108
+ return Promise . resolve ( `Basic ${ apiKeyBase64 } ` )
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ const namespaceDisplayName = namespace || '_'
115
+
116
+ console . log ( `deploying to ${ namespaceType } -based namespace '${ namespaceDisplayName } ' ...` )
117
+
118
+ if ( ! authHandler ) {
119
+ throw new Error (
120
+ `Failed to determine the authentication strategy for the ${ namespaceType } -based namespace '${ namespaceDisplayName } '`
121
+ )
74
122
}
75
123
76
- const wsk = openwhisk ( Object . assign ( { apihost, apiversion, api_key : apikey , auth_handler : authHandler , namespace, ignore_certs : ignorecerts } , options ) )
124
+ const wsk = openwhisk (
125
+ Object . assign ( { apihost, apiversion, auth_handler : authHandler , namespace, ignore_certs : ignorecerts } , options )
126
+ )
77
127
wsk . compositions = new Compositions ( wsk )
78
128
return wsk
79
129
}
@@ -90,9 +140,17 @@ class Compositions {
90
140
return Object . assign ( { } , action , httpOptions )
91
141
}
92
142
93
- const actions = ( composition . actions || [ ] ) . concat ( conductor . generate ( composition , debug , kind , timeout , memory , logs ) ) . map ( addHttpOptions )
94
- return actions . reduce ( ( promise , action ) => promise . then ( ( ) => overwrite && this . actions . delete ( action ) . catch ( ( ) => { } ) )
95
- . then ( ( ) => this . actions . create ( action ) ) , Promise . resolve ( ) )
143
+ const actions = ( composition . actions || [ ] )
144
+ . concat ( conductor . generate ( composition , debug , kind , timeout , memory , logs ) )
145
+ . map ( addHttpOptions )
146
+ return actions
147
+ . reduce (
148
+ ( promise , action ) =>
149
+ promise
150
+ . then ( ( ) => overwrite && this . actions . delete ( action ) . catch ( ( ) => { } ) )
151
+ . then ( ( ) => this . actions . create ( action ) ) ,
152
+ Promise . resolve ( )
153
+ )
96
154
. then ( ( ) => actions )
97
155
}
98
156
}
0 commit comments