Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App Name Enhancements to CHv2 #80

Merged
merged 13 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .sdkmanrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=8.0.392-tem
maven=3.9.2
6 changes: 6 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ Option 2 is probably the preferred route for most use cases. Both options 2 and

You'll need a service account user/password to run this. See the README.md file inside the library directory for what permissions the user needs.

## Custom Policies

Most of the common security policies are accounted for in the DSL. A custom policy can be used for any additional options or customization that is necessary. For an example, see the `mulesoftPolicy` sample in `library/examples/allOptions.groovy`.

To help populate the JSON config object of the desired custom policy, use the network inspector in chrome while manually configuring the policy.

# Running

If you read the DSL section, you should have a DSL file that's ready to go.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,13 @@ muleDeploy {

onPremApplication {
environment 'DEV'
applicationName 'the-app'
applicationName {
baseAppName 'the-app'
prefix 'AVI'
suffix 'xxx'
usePrefix false
useSuffix false
}
appVersion '1.2.3'
file '${builtFile}'
targetServerOrClusterName 'theServer'
Expand All @@ -129,7 +135,7 @@ muleDeploy {
is(equalTo([]))
assert actualApp instanceof OnPremDeploymentRequest
actualApp.with {
assertThat it.appName,
assertThat it.appName.normalizedAppName,
is(equalTo('the-app'))
assertThat it.environment,
is(equalTo('DEV'))
Expand Down Expand Up @@ -167,7 +173,13 @@ muleDeploy {

onPremApplication {
environment 'DEV'
applicationName 'the-app'
applicationName {
baseAppName 'the-app'
prefix 'AVI'
suffix 'xxx'
usePrefix false
useSuffix false
}
appVersion '1.2.3'
file '${builtFile}'
targetServerOrClusterName 'theServer'
Expand All @@ -187,7 +199,7 @@ muleDeploy {
is(equalTo([]))
assert actualApp instanceof OnPremDeploymentRequest
actualApp.with {
assertThat it.appName,
assertThat it.appName.normalizedAppName,
is(equalTo('the-app'))
assertThat it.environment,
is(equalTo('DEV'))
Expand Down Expand Up @@ -221,7 +233,13 @@ muleDeploy {

onPremApplication {
environment 'DEV'
applicationName 'the-app'
applicationName {
baseAppName 'the-app'
prefix 'AVI'
suffix 'xxx'
usePrefix false
useSuffix false
}
appVersion '1.2.3'
file '${builtFile}'
targetServerOrClusterName 'theServer'
Expand Down Expand Up @@ -269,7 +287,13 @@ muleDeploy {

cloudHubApplication {
environment params.env
applicationName 'the-app'
applicationName {
baseAppName 'the-app'
prefix 'AVI'
suffix 'xxx'
usePrefix true
useSuffix false
}
appVersion '1.2.3'
workerSpecs {
muleVersion params.env == 'DEV' ? '4.2.2' : '4.1.5'
Expand All @@ -280,7 +304,6 @@ muleDeploy {
clientId 'the_client_id'
clientSecret 'the_client_secret'
}
cloudHubAppPrefix 'AVI'
}
}
"""
Expand Down Expand Up @@ -363,7 +386,13 @@ muleDeploy {

onPremApplication {
environment 'DEV'
applicationName 'the-app'
applicationName {
baseAppName 'the-app'
prefix 'AVI'
suffix 'xxx'
usePrefix false
useSuffix false
}
appVersion '1.2.3'
file '${builtFile}'
targetServerOrClusterName 'theServer'
Expand Down
2 changes: 1 addition & 1 deletion cli/src/test/resources/mule4_project/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<app.runtime>replaceme</app.runtime>
<mule.maven.plugin.version>3.1.6</mule.maven.plugin.version>
<mule.maven.plugin.version>3.5.4</mule.maven.plugin.version>
</properties>

<build>
Expand Down
9 changes: 8 additions & 1 deletion library/examples/allOptions.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,14 @@ muleDeploy {
groupId 'stuff'
}
mulesoftPolicy {
version '1.2.1'
// Sample using the client id enforcement with header properties
assetId 'client-id-enforcement'
version '1.2.3'
config([
credentialsOriginHasHttpBasicAuthenticationHeader: 'customExpression',
clientIdExpression: '#[attributes.headers["client_id"]]',
clientSecretExpression: '#[attributes.headers["client_secret"]]'
])
}
azureAdJwtPolicy {
azureAdTenantId 'abcd'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@ abstract class AppDeploymentRequest {
*/
protected String environment
/**
* TODO change this
* Actual name of your application WITHOUT any kind of customer/environment prefix or suffix. Spaces in the name are not allowed and will be rejected.
* This parameter is optional. If you don't supply it, the <artifactId> from your app's POM will be used.
*/
protected String appName
protected ApplicationName applicationName
/**
* Version of the app you are deploying (e.g. <version> from the POM). This parameter is optional and if it's not supplied
* then it will be derived from the <version> parameter in the project's POM based on the JAR/ZIP
*/
protected String appVersion

AppDeploymentRequest(String appName, String appVersion, String environment) {
this.appName = appName
AppDeploymentRequest(ApplicationName applicationName, String appVersion, String environment) {
this.applicationName = applicationName
this.appVersion = appVersion
this.environment = environment
}
Expand All @@ -37,8 +38,8 @@ abstract class AppDeploymentRequest {
this.environment = environment
}

protected void setAppName(String appName) {
this.appName = appName
protected void setAppName(ApplicationName appName) {
this.applicationName = appName
}

protected void setAppVersion(String appVersion) {
Expand All @@ -49,8 +50,8 @@ abstract class AppDeploymentRequest {
return environment
}

String getAppName() {
return appName
ApplicationName getAppName() {
return this.applicationName
}

String getAppVersion() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.avioconsulting.mule.deployment.api.models.deployment

class ApplicationName {

private String baseAppName
private Boolean usePrefix
private Boolean useSuffix
private String prefix
private String suffix
private String normalizedAppName
private static final String EMPTY_STRING=''
private static final MAX_SIZE_APPLICATION_NAME = 42

ApplicationName(String baseAppName, Boolean usePrefix, Boolean useSuffix, String prefix, String suffix) {
this.baseAppName = baseAppName
this.usePrefix = usePrefix
this.useSuffix = useSuffix
this.prefix = prefix
this.suffix = suffix
// getNormalizedAppName()
}

String getBaseAppName(){
return this.baseAppName
}

String getNormalizedAppName() {
runGuards()
if(normalizedAppName == null){
if(!useSuffix && !prefix){
normalizedAppName = baseAppName.toLowerCase()
} else {
normalizedAppName = buildAppNameByOptions().toLowerCase()
}
}
runNameLengthGuard(normalizedAppName)
return normalizedAppName
}

private void runGuards(){
assert (baseAppName != null && !baseAppName.isBlank() && !baseAppName.contains(" ")) : "you should specify an non-empty baseAppName. It shouldn't contain spaces as well"
if (usePrefix == true) assert (prefix != null && !prefix.isBlank() && !prefix.contains(" ")) : "as you going to use a prefix, you should specify a non-empty one. Prefix should not contain spaces"
if (useSuffix == true) assert (suffix != null && !suffix.isBlank() && !suffix.contains(" ")) : "as you going to use a suffix, you should specify a non-empty one. Prefix should not contain spaces"

}

private void runNameLengthGuard(String normalizedAppName){
if (normalizedAppName.length() >= MAX_SIZE_APPLICATION_NAME){
throw new Exception("Maximum size of application name is ${MAX_SIZE_APPLICATION_NAME} and the provided name has ${normalizedAppName.length()} characters")
}
}


private String buildAppNameByOptions(){
// calculate prefix
String updatedPrefix=EMPTY_STRING
if(usePrefix){
updatedPrefix = prefix
}
// calculate suffix
String updatedSuffix=EMPTY_STRING
if(useSuffix){
updatedSuffix = suffix
}
def nameParts = [updatedPrefix, baseAppName, updatedSuffix]
nameParts.findAll {it != null && !it.isBlank()}.join("-")
}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package com.avioconsulting.mule.deployment.api.models.deployment

import com.avioconsulting.mule.deployment.api.models.CloudhubWorkerSpecRequest
import com.avioconsulting.mule.deployment.api.models.PomInfo
import com.avioconsulting.mule.deployment.internal.models.CloudhubAppProperties
import com.avioconsulting.mule.deployment.secure.PropertiesObfuscator
import com.fasterxml.jackson.databind.ObjectMapper
import groovy.json.JsonOutput
import groovy.transform.ToString
import groovy.xml.XmlSlurper
import groovy.xml.slurpersupport.NodeChild
import org.apache.http.HttpEntity
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.HttpMultipartMode
import org.apache.http.entity.mime.MultipartEntityBuilder

import java.nio.file.FileSystems
import java.nio.file.Files
import java.nio.file.Path

@ToString
class CloudhubDeploymentRequest extends FileBasedAppDeploymentRequest {
/**
Expand All @@ -29,10 +36,6 @@ class CloudhubDeploymentRequest extends FileBasedAppDeploymentRequest {
* will be set in the anypoint.platform.client_secret CloudHub property
*/
final String anypointClientSecret
/**
* Your "DNS prefix" for Cloudhub app uniqueness, usually a 3 letter customer ID to ensure app uniqueness.
*/
final String cloudHubAppPrefix
/**
* Mule app property overrides (the stuff in the properties tab)
*/
Expand All @@ -41,10 +44,6 @@ class CloudhubDeploymentRequest extends FileBasedAppDeploymentRequest {
* CloudHub level property overrides (e.g. region type stuff)
*/
final Map<String, String> otherCloudHubProperties
/**
* Get only property, derived from app, environment, and prefix, this the real application name that will be used in CloudHub to ensure uniqueness.
*/
final String normalizedAppName

/***
* Sets anypoint.platform.config.analytics.agent.enabled to true in CH props
Expand All @@ -63,13 +62,12 @@ class CloudhubDeploymentRequest extends FileBasedAppDeploymentRequest {
String cryptoKey,
String anypointClientId,
String anypointClientSecret,
String cloudHubAppPrefix,
String appName = null,
ApplicationName applicationName,
String appVersion = null,
Map<String, String> appProperties = [:],
Map<String, String> otherCloudHubProperties = [:],
boolean analyticsAgentEnabled = true) {
super(file, appName, appVersion, environment)
super(file, applicationName, appVersion, environment)
if (!workerSpecRequest.muleVersion) {
def propertyToUse = mule4Request ? 'app.runtime' : 'mule.version'
def rawVersion = parsedPomProperties.props[propertyToUse]
Expand All @@ -83,19 +81,15 @@ class CloudhubDeploymentRequest extends FileBasedAppDeploymentRequest {
this.cryptoKey = cryptoKey
this.anypointClientId = anypointClientId
this.anypointClientSecret = anypointClientSecret
this.cloudHubAppPrefix = cloudHubAppPrefix
this.appProperties = appProperties
this.otherCloudHubProperties = otherCloudHubProperties
if (this.appName.contains(' ')) {
throw new Exception("Runtime Manager does not like spaces in app names and you specified '${this.appName}'!")
}
def newAppName = "${cloudHubAppPrefix}-${this.appName}-${environment}"
def appNameLowerCase = newAppName.toLowerCase()
if (appNameLowerCase != newAppName) {
newAppName = appNameLowerCase

//normalize name
if(!applicationName.baseAppName){
applicationName.baseAppName = parsedPomProperties.artifactId
}
normalizedAppName = newAppName
this.cloudhubAppProperties = new CloudhubAppProperties(this.appName,
//
this.cloudhubAppProperties = new CloudhubAppProperties(applicationName.baseAppName,
environment.toLowerCase(),
cryptoKey,
anypointClientId,
Expand Down Expand Up @@ -126,7 +120,7 @@ class CloudhubDeploymentRequest extends FileBasedAppDeploymentRequest {
props += this.autoDiscoveries
def result = [
// CloudHub's API calls the Mule application the 'domain'
domain : normalizedAppName,
domain : this.applicationName.normalizedAppName,
muleVersion : workerSpecRequest.versionInfo,
region : workerSpecRequest.awsRegion?.awsCode,
monitoringAutoRestart : true,
Expand Down Expand Up @@ -163,4 +157,27 @@ class CloudhubDeploymentRequest extends FileBasedAppDeploymentRequest {
PropertiesObfuscator.obfuscateMap(cloudhubAppInfo,"properties")
}

@Lazy
protected PomInfo parsedPomProperties = {
def zipOrJarPath = getFile().toPath()
FileSystems.newFileSystem(zipOrJarPath,
null).withCloseable { fs ->
def pomXmlPath = Files.walk(fs.getPath('/META-INF/maven')).find { p ->
p.endsWith('pom.xml')
} as Path
assert pomXmlPath: 'Was not able to find pom.xml in ZIP/JAR'
def parser = new XmlSlurper().parseText(pomXmlPath.text)
def props = parser.properties.children().collectEntries { NodeChild node ->
[node.name(), node.text()]
}
def textFromNode = { String element ->
def res = parser[element][0] as NodeChild
res.text()
}
return new PomInfo(textFromNode('groupId'),
textFromNode('artifactId'),
textFromNode('version'),
props)
} as PomInfo
}()
}
Loading