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

MIP-325 Able to parse an app and print property file names #6

Merged
merged 5 commits into from
Jul 1, 2020
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 src/main/groovy/com/avioconsulting/mule/MuleLinter.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import com.avioconsulting.mule.linter.rule.pom.MuleMavenPluginVersionRule
import com.avioconsulting.mule.linter.rule.pom.MunitVersionRule
import com.avioconsulting.mule.linter.rule.pom.MuleRuntimeVersionRule
import com.avioconsulting.mule.linter.rule.pom.PomExistsRule
import com.avioconsulting.mule.linter.rule.property.PropertyFileNamingRule
import com.avioconsulting.mule.linter.rule.property.PropertyFilePropertyCountRule

class MuleLinter {

Expand All @@ -23,6 +25,8 @@ class MuleLinter {
rules.addRule(new MuleMavenPluginVersionRule('3.3.5'))
rules.addRule(new MunitVersionRule('2.2.1'))
rules.addRule(new MuleRuntimeVersionRule('4.2.1'))
rules.addRule(new PropertyFileNamingRule(['dev', 'test']))
rules.addRule(new PropertyFilePropertyCountRule(['dev', 'test', 'uat', 'prod'], '${env}.properties'))

// Create the executor
RuleExecutor exe = new RuleExecutor(app, rules)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import picocli.CommandLine
@CommandLine.Command(name = 'MuleLinter', header = '%n@|green Mule Linter|@')
class MuleLinterCli implements Runnable {

@CommandLine.Option(names = ['-r', '--rules'], required = true, description = 'Rule definition file')
@CommandLine.Option(names = ['-r', '--rules'], required = false, description = 'Rule definition file')
String rules

@CommandLine.Option(names = ['-d', '--dir'], required = true, description = 'Application Directory')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,35 @@ class Application {
static final String POM_FILE = 'pom.xml'

File applicationPath
List<ProjectFile> files = []
List<PropertyFile> propertyFiles = []
PomFile pomFile
String name

Application(File applicationPath) {
this.applicationPath = applicationPath
if (!this.applicationPath.exists()) {
throw new FileNotFoundException( APPLICATION_DOES_NOT_EXIST + applicationPath.absolutePath)
}
pomFile = new PomFile(applicationPath, POM_FILE)
this.name = pomFile.getArtifactId()

loadPropertyFiles()
}

File getApplicationPath() {
return applicationPath
void loadPropertyFiles() {
File resourcePath = new File(applicationPath, 'src/main/resources')
if (!resourcePath.exists()) {
throw new FileNotFoundException( APPLICATION_DOES_NOT_EXIST + resourcePath.absolutePath)
}
resourcePath.eachDirRecurse { dir ->
dir.eachFileMatch(~/.*.properties/) { file ->
propertyFiles.add(new PropertyFile(file))
}
}
kkingavio marked this conversation as resolved.
Show resolved Hide resolved
}

void setApplicationPath(File applicationPath) {
this.applicationPath = applicationPath
File getApplicationPath() {
return applicationPath
}

PomFile getPomFile() {
Expand All @@ -34,4 +46,12 @@ class Application {
return file.exists()
}

String getName() {
return name
}

List<PropertyFile> getPropertyFiles() {
return propertyFiles
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ class PomFile extends ProjectFile {
this(new File(application, fileName))
}

String getArtifactId() {
return exists ? model?.artifactId : ''
}

void setArtifactId(String artifactId) {
this.artifactId = artifactId
}

Boolean doesExist() {
return exists
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package com.avioconsulting.mule.linter.model
class ProjectFile {

File file
String name

ProjectFile(File f) {
file = f
this.name = f.name
}

File getFile() {
Expand All @@ -16,4 +18,12 @@ class ProjectFile {
this.file = file
}

String getName() {
return name
}

void setName(String name) {
this.name = name
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.avioconsulting.mule.linter.model

class PropertyFile {

File file
String name
Properties properties

PropertyFile(File file) {
this.file = file
this.name = file.name
loadProperties()
}

void loadProperties() {
Properties props = new Properties()
file.withInputStream {
props.load(it)
}
properties = props
}

File getFile() {
return file
}

Integer getPropertyCount() {
return properties.size()
}

String getProperty(String propertyName) {
return properties.getProperty(propertyName)
}

void setFile(File file) {
this.file = file
}

String getName() {
return name
}

void setName(String name) {
this.name = name
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.avioconsulting.mule.linter.rule.property

import com.avioconsulting.mule.linter.model.Application
import com.avioconsulting.mule.linter.model.RuleViolation
import com.avioconsulting.mule.linter.model.Rule
import groovy.text.SimpleTemplateEngine

@SuppressWarnings(['GStringExpressionWithinString'])
class PropertyFileNamingRule extends Rule {

static final String RULE_ID = 'PROPERTY_FILE_NAMING'
static final String RULE_NAME = 'Property File Naming Rule'
static final String RULE_VIOLATION_MESSAGE = 'Missing property file, files must match naming pattern: '
static final String DEFAULT_PATTERN = '${appname}-${env}.properties'

String[] environments
String pattern

/**
* A new PropertyFileNamingRule for a list of environments. This ensures that
* there is at least one file that matches the pattern '${appname}-${env}.properties'
* for each environment.
*
* @param environments List of environments to check for files
*/
PropertyFileNamingRule(List<String> environments) {
this(environments, DEFAULT_PATTERN)
}

/**
* A new PropertyFileNamingRule for a list of environments. This ensures that
* there is at least one file that matches the pattern for each environment.
* Possible pattern variables ${env} and ${appname}.
*
* @param environments List of environments to check for files
* @param pattern String pattern to search. ex. '${appname}-${env}.properties'
*/
PropertyFileNamingRule(List<String> environments, String pattern) {
this.ruleId = RULE_ID
this.ruleName = RULE_NAME
this.environments = environments
this.pattern = pattern
}

@Override
List<RuleViolation> execute(Application app) {
List<RuleViolation> violations = []

List propertyFilenames = app.propertyFiles*.getName()

environments.each { env ->
Map<String, String> binding = ['appname':app.name, 'env':env]
String fileName = new SimpleTemplateEngine().createTemplate(pattern).make(binding)
if (!(fileName in propertyFilenames)) {
violations.add(new RuleViolation(this, fileName, 0, RULE_VIOLATION_MESSAGE + pattern))
}
}

return violations
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.avioconsulting.mule.linter.rule.property

import com.avioconsulting.mule.linter.model.Application
import com.avioconsulting.mule.linter.model.PropertyFile
import com.avioconsulting.mule.linter.model.Rule
import com.avioconsulting.mule.linter.model.RuleViolation
import groovy.text.SimpleTemplateEngine

class PropertyFilePropertyCountRule extends Rule {

static final String RULE_ID = 'PROPERTY_FILE_COUNT_MISMATCH'
static final String RULE_NAME = 'Property File Count Mismatch'
static final String RULE_VIOLATION_MESSAGE = 'Properties files do not have matching number of properties. '
static final String DEFAULT_PATTERN = '${appname}-${env}.properties'

String[] environments
String pattern

PropertyFilePropertyCountRule(List<String> environments) {
this(environments, DEFAULT_PATTERN)
}

PropertyFilePropertyCountRule(List<String> environments, String pattern) {
this.ruleId = RULE_ID
this.ruleName = RULE_NAME
this.environments = environments
this.pattern = pattern
}

@Override
List<RuleViolation> execute(Application app) {
List<RuleViolation> violations = []

List<PropertyFile> propFiles = getValidPropertyFiles(getValidPropertyFilenames(app.name), app.propertyFiles)

if(propFiles*.getPropertyCount().unique().size() > 1) {
Map counts = propFiles.collectEntries { [it.getName(), it.getPropertyCount()]}
propFiles.each { file ->
violations.add(new RuleViolation(this, file.getName(), 0, RULE_VIOLATION_MESSAGE + counts))
}
}

return violations
}

List getValidPropertyFilenames(String applicationName) {
List validPropertyFilenames = []
environments.each { env ->
Map<String, String> binding = ['appname':applicationName, 'env':env]
String fileName = new SimpleTemplateEngine().createTemplate(pattern).make(binding)
validPropertyFilenames.add(fileName)
}
return validPropertyFilenames
}

List getValidPropertyFiles(List validPropertyFilenames, List propertyFiles) {
List<PropertyFile> validPropertyFiles = []
propertyFiles.each {
if(it.getName() in validPropertyFilenames){
validPropertyFiles.add(it)
}
}
return validPropertyFiles
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.avioconsulting.mule.linter.rule.property

import com.avioconsulting.mule.linter.model.Application
import com.avioconsulting.mule.linter.model.Rule
import com.avioconsulting.mule.linter.model.RuleViolation
import spock.lang.Specification

@SuppressWarnings(['MethodName', 'MethodReturnTypeRequired', 'GStringExpressionWithinString'])
class PropertyFileNamingRuleTest extends Specification {

private static final List<String> ENVS = ['dev', 'test', 'prod']
private static final String NAMING_PATTERN = '${appname}.${env}.properties'
private static final String APP_NAME = 'SampleMuleApp'

def 'Property File Naming Rule check with pattern'() {
given:
Rule rule = new PropertyFileNamingRule(ENVS, NAMING_PATTERN)

when:
File appDir = new File(this.class.classLoader.getResource(application).file)
Application app = new Application(appDir)
List<RuleViolation> violations = rule.execute(app)

then:
violations.size() == size
violations[0].fileName == 'sample-mule-app.dev.properties'
violations[0].message.contains(NAMING_PATTERN)

where:
application | size
APP_NAME | 1
}

def 'Property File Naming Rule check default pattern'() {
given:
Rule rule = new PropertyFileNamingRule(ENVS)

when:
File appDir = new File(this.class.classLoader.getResource(application).file)
Application app = new Application(appDir)
List<RuleViolation> violations = rule.execute(app)

then:
violations.size() == size
violations[0].fileName == 'sample-mule-app-prod.properties'

where:
application | size
APP_NAME | 1
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.avioconsulting.mule.linter.rule.property

import com.avioconsulting.mule.linter.model.Application
import com.avioconsulting.mule.linter.model.Rule
import com.avioconsulting.mule.linter.model.RuleViolation
import spock.lang.Specification

@SuppressWarnings(['MethodName', 'MethodReturnTypeRequired', 'GStringExpressionWithinString'])
class PropertyFilePropertyCountRuleTest extends Specification {

private static final List<String> ENVS = ['dev', 'test', 'uat', 'prod']
private static final String NAMING_PATTERN = '${env}.properties'
private static final String APP_NAME = 'SampleMuleApp'

def 'Property File Count mismatch with pattern'() {
given:
Rule rule = new PropertyFilePropertyCountRule(['dev', 'test', 'uat', 'prod'], NAMING_PATTERN)

when:
File appDir = new File(this.class.classLoader.getResource(APP_NAME).file)
Application app = new Application(appDir)
List<RuleViolation> violations = rule.execute(app)

then:
violations.size() == 4
violations[0].message.contains('[uat.properties:6, test.properties:6, dev.properties:4, prod.properties:7]')
}

def 'Property File Count matching with pattern'() {
given:
Rule rule = new PropertyFilePropertyCountRule(['test', 'uat'], NAMING_PATTERN)

when:
File appDir = new File(this.class.classLoader.getResource(APP_NAME).file)
Application app = new Application(appDir)
List<RuleViolation> violations = rule.execute(app)

then:
violations.size() == 0
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
prop=value
Loading