mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-01-16 05:16:08 +02:00
Invalidate cache for neo deployments (#2209)
* Add additional parameters for invalidating cache * Fetch bearer token * Fetch x-csrf token * Add echo for testing * Add echo * Add another echo * Check status * Debug * Clean up * Throw exception * Code review changes * Review changes * Add test * Fix tests * Fetch bearer token * Fetch x-csrf token * Add echo for testing * Add echo * Add another echo * Check status * Debug * Resolve conflicts * Resolve conflicts * Code review changes * Review changes * fix conflicts * Fix indent * Add new parameter to define portal landscape region * Add default value for new param * Fix test * Remove example Co-authored-by: Oliver Feldmann <oliver.feldmann@sap.com> * Check cache invalidation for html5 apps * Add nesting Co-authored-by: Oliver Feldmann <oliver.feldmann@sap.com> * Add docu for invalidating cache for html5 apps (#2306) * Add docu for invalidating cache for html5 apps * Improve content * Docu review changes * Remove heading Co-authored-by: Sarah Lendle <44202907+SarahLendle@users.noreply.github.com> * Update documentation/docs/steps/neoDeploy.md Co-authored-by: Sarah Lendle <44202907+SarahLendle@users.noreply.github.com> Co-authored-by: Sarah Lendle <44202907+SarahLendle@users.noreply.github.com> Co-authored-by: Oliver Feldmann <oliver.feldmann@sap.com> Co-authored-by: Sarah Lendle <44202907+SarahLendle@users.noreply.github.com>
This commit is contained in:
parent
e859ed3375
commit
0234e4908c
BIN
documentation/docs/images/oauthClientCreation.png
Normal file
BIN
documentation/docs/images/oauthClientCreation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
documentation/docs/images/portalSiteSetToDefault.png
Normal file
BIN
documentation/docs/images/portalSiteSetToDefault.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
documentation/docs/images/portalSubscription.png
Normal file
BIN
documentation/docs/images/portalSubscription.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
@ -54,3 +54,46 @@ steps:
|
||||
account: <myDeployAccount>
|
||||
host: hana.example.org
|
||||
```
|
||||
|
||||
## Example for invalidating the cache
|
||||
|
||||
Set the parameter `invalidateCache` to `true` to clean up the cache of an SAP Fiori launchpad site by refreshing the content of HTML5 applications deployed in it.
|
||||
|
||||
**Note:** This section is only applicable for HTML5 applications accessed through an SAP Fiori launchpad site.
|
||||
|
||||
Setting this parameter to `true` requires additional configuration:
|
||||
|
||||
### Create an OAuth credential
|
||||
|
||||
1. In your subaccount, choose **OAuth**.
|
||||
|
||||
![OAuth client creation](../images/oauthClientCreation.png)
|
||||
|
||||
2. In the **Subscription** field, select the portal landscape to which you would like to subscribe, for example, `portal/nwc` or `portal/sandbox`.
|
||||
|
||||
![Portal subscription](../images/portalSubscription.png)
|
||||
|
||||
3. From the drop-down menu in the **Authorization Grant** field, choose **Client Credentials**.
|
||||
|
||||
4. In the **Secret** field, enter a user-defined password and save your changes.
|
||||
|
||||
5. In Jenkins, create new username/password credentials. As username, use the client ID and as password, use the client secret.
|
||||
|
||||
### Configure the site ID
|
||||
|
||||
When you're logged in to the portal service, you can retrieve the site ID. Either configure it in your configuration file or set the site as default through the **Site Directory** tile.
|
||||
If you don't set it as default, configure the parameter `siteId` as follows in your configuration file:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
<...>
|
||||
neoDeploy:
|
||||
neo:
|
||||
account: <myDeployAccount>
|
||||
host: hana.example.org
|
||||
credentialsId: 'my-credentials-id'
|
||||
invalidateCache: true
|
||||
portalLandscape: "cloudnwcportal"
|
||||
oauthCredentialId: <OAUTH_CREDENTIAL_ID>
|
||||
siteId: <PORTAL_SITE_ID> # not required, if the default site is already set in the portal service (SAP Cloud Platform)
|
||||
```
|
||||
|
@ -333,6 +333,7 @@ steps:
|
||||
neo:
|
||||
size: 'lite'
|
||||
credentialsId: 'CI_CREDENTIALS_ID'
|
||||
portalLandscape: "cloudnwcportal"
|
||||
multicloudDeploy:
|
||||
cfTargets: []
|
||||
neoTargets: []
|
||||
|
@ -3,9 +3,12 @@ import com.sap.piper.Utils
|
||||
|
||||
import groovy.lang.Script
|
||||
import hudson.AbortException
|
||||
import util.JenkinsReadJsonRule
|
||||
|
||||
import static org.hamcrest.Matchers.allOf
|
||||
import static org.hamcrest.Matchers.contains
|
||||
import static org.hamcrest.Matchers.containsString
|
||||
import static org.hamcrest.Matchers.hasItem
|
||||
import static org.hamcrest.Matchers.not
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
@ -52,7 +55,9 @@ class NeoDeployTest extends BasePiperTest {
|
||||
.around(shellRule)
|
||||
.around(new JenkinsCredentialsRule(this)
|
||||
.withCredentials('myCredentialsId', 'anonymous', '********')
|
||||
.withCredentials('CI_CREDENTIALS_ID', 'defaultUser', '********'))
|
||||
.withCredentials('CI_CREDENTIALS_ID', 'defaultUser', '********')
|
||||
.withCredentials('testOauthId', 'clientId', '********'))
|
||||
.around(new JenkinsReadJsonRule(this))
|
||||
.around(stepRule)
|
||||
.around(new JenkinsLockRule(this))
|
||||
.around(new JenkinsWithEnvRule(this))
|
||||
@ -417,6 +422,43 @@ class NeoDeployTest extends BasePiperTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidateCache_Success_Test() {
|
||||
|
||||
nullScript.commonPipelineEnvironment.configuration = [steps: [neoDeploy: [neo: [host: 'test.deploy.host.com', account: 'trialuser123', invalidateCache: true, oauthCredentialId: 'testOauthId', siteId: "12346"]]]]
|
||||
fileExistsRule.registerExistingFile('./target/artifact.war')
|
||||
|
||||
shellRule.setReturnValue(JenkinsShellCallRule.Type.REGEX, "https:\\/\\/oauthasservices-trialuser123\\.test\\.deploy\\.host\\.com\\/oauth2\\/api\\/v1\\/token", "{\"access_token\":\"xxx\"}")
|
||||
shellRule.setReturnValue(JenkinsShellCallRule.Type.REGEX, "fiori\\/api\\/v1\\/csrf", "X-CSRF-Token=xxx")
|
||||
shellRule.setReturnValue(JenkinsShellCallRule.Type.REGEX, "fiori\\/v1\\/operations\\/invalidateCache", "{\"statusCode\":\"200\"}")
|
||||
|
||||
stepRule.step.neoDeploy(script: nullScript,
|
||||
source: archiveName,
|
||||
deployMode: 'mta')
|
||||
|
||||
Assert.assertThat(shellRule.shell, hasItem(containsString("curl -X POST -u \"clientId:********\" --fail \"https://oauthasservices-trialuser123.test.deploy.host.com/oauth2/api/v1/token?grant_type=client_credentials&scope=write,read")))
|
||||
Assert.assertThat(shellRule.shell[3], containsString("#!/bin/bash curl -i -L -c 'cookies.jar' -H 'X-CSRF-Token: Fetch' -H \"Authorization: Bearer xxx\" --fail \"https://cloudnwcportal-trialuser123.test.deploy.host.com/fiori/api/v1/csrf\""))
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidateCache_notPerformed_warFiles() {
|
||||
|
||||
nullScript.commonPipelineEnvironment.configuration = [steps: [neoDeploy: [neo: [host: 'test.deploy.host.com', account: 'trialuser123', invalidateCache: true]]]]
|
||||
|
||||
stepRule.step.neoDeploy(script: nullScript,
|
||||
neo: [
|
||||
application: 'testApp',
|
||||
runtime: 'neo-javaee6-wp',
|
||||
runtimeVersion: '2.125',
|
||||
size: 'lite',
|
||||
],
|
||||
deployMode: 'warParams',
|
||||
warAction: 'deploy',
|
||||
source: warArchiveName)
|
||||
|
||||
assertThat(loggingRule.log, containsString("Invalidation of cache is ignored. It is performed only for html5 applications."))
|
||||
}
|
||||
|
||||
@Test
|
||||
void warFileParamsDeployModeTest() {
|
||||
|
||||
|
@ -41,7 +41,7 @@ import static com.sap.piper.Prerequisites.checkScript
|
||||
* @mandatory for deployMode=warParams
|
||||
*/
|
||||
'host',
|
||||
/**
|
||||
/**
|
||||
* The path to the .properties file in which all necessary deployment properties for the application are defined.
|
||||
* @parentConfigKey neo
|
||||
* @mandatory for deployMode=warPropertiesFile
|
||||
@ -59,16 +59,37 @@ import static com.sap.piper.Prerequisites.checkScript
|
||||
* @mandatory for deployMode=warParams
|
||||
*/
|
||||
'runtimeVersion',
|
||||
/**
|
||||
/**
|
||||
* Compute unit (VM) size. Acceptable values: lite, pro, prem, prem-plus.
|
||||
* @parentConfigKey neo
|
||||
*/
|
||||
'size',
|
||||
/**
|
||||
/**
|
||||
* String of VM arguments passed to the JVM.
|
||||
* @parentConfigKey neo
|
||||
*/
|
||||
'vmArguments'
|
||||
'vmArguments',
|
||||
/**
|
||||
* Boolean to enable/disable invalidating the cache after deployment.
|
||||
* @possibleValues `true`, `false`
|
||||
* @parentConfigKey neo
|
||||
*/
|
||||
'invalidateCache',
|
||||
/**
|
||||
* Portal landscape region subscribed to in SAP Cloud Platform.
|
||||
* @parentConfigKey neo
|
||||
*/
|
||||
'portalLandscape',
|
||||
/**
|
||||
* UsernamePassword type credential containing SAP Cloud Platform OAuth client ID and client secret.
|
||||
* @parentConfigKey neo
|
||||
*/
|
||||
'oauthCredentialId',
|
||||
/**
|
||||
* Site ID of the SAP Fiori Launchpad containing the SAP Fiori app. If not set, the cache of the default site, as defined in the Portal service, is invalidated.
|
||||
* @parentConfigKey neo
|
||||
*/
|
||||
'siteId'
|
||||
]
|
||||
|
||||
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([
|
||||
@ -216,11 +237,84 @@ void call(parameters = [:]) {
|
||||
lock("$STEP_NAME:${neoCommandHelper.resourceLock()}") {
|
||||
deploy(script, configuration, neoCommandHelper, configuration.dockerImage, deployMode)
|
||||
}
|
||||
if(configuration.neo.invalidateCache == true) {
|
||||
if (configuration.deployMode == 'mta') {
|
||||
echo "Triggering invalidation of cache for html5 applications"
|
||||
invalidateCache(configuration)
|
||||
} else {
|
||||
echo "Invalidation of cache is ignored. It is performed only for html5 applications."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private invalidateCache(configuration){
|
||||
def account = configuration.neo.account
|
||||
def host = configuration.neo.host
|
||||
def portalLandscape = configuration.neo.portalLandscape
|
||||
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: configuration.neo.oauthCredentialId,
|
||||
passwordVariable: 'OAUTH_NEO_CLIENT_SECRET',
|
||||
usernameVariable: 'OAUTH_NEO_CLIENT_ID')]) {
|
||||
def bearerTokenResponse = sh(
|
||||
script: """#!/bin/bash
|
||||
curl -X POST -u "${OAUTH_NEO_CLIENT_ID}:${OAUTH_NEO_CLIENT_SECRET}" \
|
||||
--fail \
|
||||
"https://oauthasservices-${account}.${host}/oauth2/api/v1/token?grant_type=client_credentials&scope=write,read"
|
||||
""",
|
||||
returnStdout: true)
|
||||
def bearerToken = readJSON(text: bearerTokenResponse).access_token
|
||||
|
||||
echo "Retrieved bearer token."
|
||||
|
||||
def fetchXcsrfTokenResponse = sh(
|
||||
script: """#!/bin/bash
|
||||
curl -i -L \
|
||||
-c 'cookies.jar' \
|
||||
-H 'X-CSRF-Token: Fetch' \
|
||||
-H "Authorization: Bearer ${bearerToken}" \
|
||||
--fail \
|
||||
"https://${portalLandscape}-${account}.${host}/fiori/api/v1/csrf"
|
||||
""",
|
||||
returnStdout: true)
|
||||
|
||||
def xcsrfToken = readProperties(text: fetchXcsrfTokenResponse)["X-CSRF-Token"]
|
||||
def siteId = configuration.neo.siteId ?: ""
|
||||
|
||||
if(! siteId){
|
||||
echo "Using the default site defined in Portal service and invalidating the cache."
|
||||
}
|
||||
else{
|
||||
echo "Invalidating the cache for site with Id: ${siteId}."
|
||||
}
|
||||
def statusCode = sh(
|
||||
script: """#!/bin/bash
|
||||
curl -X POST -L \
|
||||
-b 'cookies.jar' \
|
||||
-H "X-CSRF-Token: ${xcsrfToken}" \
|
||||
-H "Authorization: Bearer ${bearerToken}" \
|
||||
-d "{\"siteId\":${siteId}}" \
|
||||
-so /dev/null \
|
||||
-w '%{response_code}' \
|
||||
"https://${portalLandscape}-${account}.${host}/fiori/v1/operations/invalidateCache"
|
||||
""",
|
||||
returnStdout: true).trim()
|
||||
|
||||
if(! siteId && statusCode == "500") {
|
||||
error "Invalidating the cache failed. " +
|
||||
"As no siteId is set, the default site defined in the portal UI is used. " +
|
||||
"Please verify a default site is defined in Portal service. " +
|
||||
"Alternatively, configure the siteId parameter for this step to invalidate the cache of that specific site."
|
||||
} else if(! statusCode == "200" || ! statusCode == "201" ){
|
||||
error "Invalidating the cache failed with response code: ${statusCode}."
|
||||
}
|
||||
echo "Successfully invalidated the cache."
|
||||
}
|
||||
}
|
||||
|
||||
private deploy(script, Map configuration, NeoCommandHelper neoCommandHelper, dockerImage, DeployMode deployMode) {
|
||||
|
||||
String logFolder = "logs/neo/${UUID.randomUUID()}"
|
||||
|
Loading…
Reference in New Issue
Block a user