-
Notifications
You must be signed in to change notification settings - Fork 724
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
Schema Generation for nested yml configurations #1027
Changes from 97 commits
774506b
7051ca9
f1b2d30
17079c7
886bc5a
0271cd3
522f4e5
f264c70
076fe14
2bd7f9d
0da381b
3d45f6b
cd9a9dd
4bf306c
4657e0c
c734c0f
fe1ce60
8108038
38dad38
d89e24c
3c4510c
f079505
76c0932
623914f
13e893a
2ede6f6
ec07960
448c4a2
3165323
ad57f8d
14197bc
a338fbc
d0f9349
6c4cb3c
901ac01
4df5e1e
81b9a68
fd886c8
6c42055
b0b870b
fe7b0b8
dcd5f6f
122c8d9
e5bde57
b97f380
1e0a6a2
d0083d8
a030035
2b105a4
79892a2
51ae5fd
cee3cf6
1f72339
67c3f81
dff9199
5388f66
e992aee
0e9e3bd
5bacdd2
b07c22b
9bc089a
94e14d4
a96a4f7
802c9c9
d50ad6e
26341c4
3ce5e2b
b92032d
5e9ce85
a71b71e
ce565f2
cd01391
e50c94f
55e0216
80221ea
2ef14a3
53342bf
2403838
0395bea
30fdbf8
912b46d
603a577
d271135
896d2cb
ee1c946
6ab2a31
3e32f25
3be3926
e7b2a8f
314f1a7
b646a04
423ee6c
d5d10f4
1cdd881
1040a6a
a242048
0cfde4a
1aa84b1
1ff2aaf
15a7500
b468ee9
772445a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package io.jenkins.plugins.casc; | ||
|
||
import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithReadmeRule; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
|
||
import static io.jenkins.plugins.casc.misc.Util.convertYamlFileToJson; | ||
import static io.jenkins.plugins.casc.misc.Util.validateSchema; | ||
import static org.hamcrest.Matchers.empty; | ||
import static org.junit.Assert.assertThat; | ||
|
||
public class AzureKeyVaultTest { | ||
|
||
@Rule | ||
public JenkinsConfiguredWithReadmeRule j = new JenkinsConfiguredWithReadmeRule(); | ||
|
||
@Test | ||
public void validJsonSchema() throws Exception { | ||
assertThat( | ||
validateSchema(convertYamlFileToJson(this, "azureKeyVault.yml")), | ||
empty()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
unclassified: | ||
azureKeyVault: | ||
keyVaultURL: https://not-a-real-vault.vault.azure.net | ||
credentialID: service-principal |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
unclassified: | ||
slackNotifier: | ||
teamDomain: workspace | ||
tokenCredentialId: slack-token |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
unclassified: | ||
sonarGlobalConfiguration: | ||
buildWrapperEnabled: false | ||
installations: | ||
- additionalAnalysisProperties: sonar.organization=jenkinsci | ||
name: SonarQube | ||
serverAuthenticationToken: 'sonarcloud-api-token' | ||
serverUrl: 'https://sonarcloud.io' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
unclassified: | ||
sonarGlobalConfiguration: # mandatory | ||
buildWrapperEnabled: true | ||
installations: # mandatory | ||
- name: "TEST" # id of the SonarQube configuration - to be used in jobs | ||
serverUrl: "http://url:9000" | ||
#credentialsId: token-sonarqube # id of the credentials containing sonar auth token (since 2.9 version) | ||
serverAuthenticationToken: "token" # for retrocompatibility with versions < 2.9 | ||
mojoVersion: "mojoVersion" | ||
additionalProperties: "blah=blah" | ||
additionalAnalysisProperties: "additionalAnalysisProperties" | ||
triggers: | ||
skipScmCause: true | ||
skipUpstreamCause: true | ||
envVar: "envVar" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,6 +61,7 @@ public class Attribute<Owner, Type> { | |
private Setter<Owner, Type> setter; | ||
private Getter<Owner, Type> getter; | ||
private boolean secret; | ||
private boolean isJsonSchema; | ||
|
||
private boolean deprecated; | ||
|
||
|
@@ -111,6 +112,14 @@ public Class<? extends AccessRestriction>[] getRestrictions() { | |
return restrictions != null ? restrictions : EMPTY; | ||
} | ||
|
||
/** | ||
* Set jsonSchema is used to tell the describe function to call the describe structure | ||
* so that it supports and returns a nested structure | ||
*/ | ||
public void setJsonSchema(boolean jsonSchema) { | ||
isJsonSchema = jsonSchema; | ||
} | ||
|
||
public boolean isRestricted() { | ||
return restrictions != null && restrictions.length > 0; | ||
} | ||
|
@@ -235,8 +244,12 @@ public CNode describe(Owner instance, ConfigurationContext context) throws Confi | |
if (multiple) { | ||
Sequence seq = new Sequence(); | ||
if (o.getClass().isArray()) o = Arrays.asList((Object[]) o); | ||
for (Object value : (Iterable) o) { | ||
seq.add(_describe(c, context, value, shouldBeMasked)); | ||
if (o instanceof Iterable) { | ||
timja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (Object value : (Iterable) o) { | ||
seq.add(_describe(c, context, value, shouldBeMasked)); | ||
} | ||
} else { | ||
LOGGER.log(Level.FINE, o.getClass().toString() + " is not iterable"); | ||
} | ||
return seq; | ||
} | ||
|
@@ -249,6 +262,45 @@ public CNode describe(Owner instance, ConfigurationContext context) throws Confi | |
} | ||
} | ||
|
||
/** | ||
* This function is for the JSONSchemaGeneration | ||
* @param instance Owner Instance | ||
* @param context Context to be passed | ||
* @return CNode object describing the structure of the node | ||
*/ | ||
timja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public CNode describeForSchema (Owner instance, ConfigurationContext context) { | ||
final Configurator c = context.lookup(type); | ||
if (c == null) { | ||
return new Scalar("FAILED TO EXPORT\n" + instance.getClass().getName()+"#"+name + | ||
": No configurator found for type " + type); | ||
} | ||
try { | ||
Object o = getType(); | ||
if (o == null) { | ||
return null; | ||
} | ||
|
||
// In Export we sensitive only those values which do not get rendered as secrets | ||
boolean shouldBeMasked = isSecret(instance); | ||
if (multiple) { | ||
Sequence seq = new Sequence(); | ||
if (o.getClass().isArray()) o = Arrays.asList(o); | ||
if(o instanceof Iterable) { | ||
sladyn98 marked this conversation as resolved.
Show resolved
Hide resolved
sladyn98 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (Object value : (Iterable) o) { | ||
seq.add(_describe(c, context, value, shouldBeMasked)); | ||
} | ||
} | ||
return seq; | ||
} | ||
return _describe(c, context, o, shouldBeMasked); | ||
} catch (Exception e) { | ||
// Don't fail the whole export, prefer logging this error | ||
LOGGER.log(Level.WARNING, "Failed to export", e); | ||
return new Scalar("FAILED TO EXPORT\n" + instance.getClass().getName() + "#" + name + ": " | ||
+ printThrowable(e)); | ||
} | ||
} | ||
|
||
/** | ||
* Describes a node. | ||
* @param c Configurator | ||
|
@@ -261,7 +313,12 @@ public CNode describe(Owner instance, ConfigurationContext context) throws Confi | |
*/ | ||
private CNode _describe(Configurator c, ConfigurationContext context, Object value, boolean shouldBeMasked) | ||
throws Exception { | ||
CNode node = c.describe(value, context); | ||
CNode node; | ||
if(isJsonSchema) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Casz Added this so that it would not throw any casting errors, since in the descirbe structure we were initally calling with value whereas now we needed the type. This reduces the castClassException There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this still required?
sladyn98 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
node = c.describeStructure(value, context); | ||
} else { | ||
node = c.describe(value, context); | ||
} | ||
if (shouldBeMasked && node instanceof Scalar) { | ||
((Scalar)node).sensitive(true); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
import org.apache.commons.lang.StringUtils; | ||
import org.jenkinsci.Symbol; | ||
|
||
|
||
/** | ||
* Define a {@link Configurator} which handles a configuration element, identified by name. | ||
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a> | ||
|
@@ -167,4 +168,20 @@ default CNode describe(T instance, ConfigurationContext context) throws Exceptio | |
return mapping; | ||
} | ||
|
||
@CheckForNull | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs Javadoc since it will be consumed by plugins. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah added javadoc. Confused about the |
||
default CNode describeStructure(T instance, ConfigurationContext context) | ||
timja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
throws Exception { | ||
Mapping mapping = new Mapping(); | ||
for (Attribute attribute : getAttributes()) { | ||
if(context.getMode().equals("JSONSchema")) { | ||
sladyn98 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
attribute.setJsonSchema(true); | ||
} | ||
CNode value = attribute.describeForSchema(instance, context); | ||
if (value != null) { | ||
mapping.put(attribute.getName(), attribute.getType().getSimpleName()); | ||
} | ||
} | ||
return mapping; | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add Javadoc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added +1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this still required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for closing now it is the separate thread