Improve documenation

This commit is contained in:
René Scheibe 2019-02-24 00:01:22 +01:00 committed by Joseph Petersen
parent 8a9ac35575
commit 74c7d1a4e6
42 changed files with 262 additions and 274 deletions

View File

@ -41,7 +41,7 @@
- [SECURITY] prevent directly entered private key to be exported in plain test
- fix and improve generated documentation
- use BulkChange to avoid repeated calls to save()
- list available attributes when unknown found in yaml to help diagnose mistakes
- list available attributes when unknown found in YAML to help diagnose mistakes
- log a warning when descriptor with unexpected design is detected
## 1.1

View File

@ -1,10 +1,10 @@
= Plugin Compatibility with Configuration-as-code plugin
= Plugin Compatibility with configuration-as-code plugin
This document captures the ongoing status of plugins known to be compatible or incompatible.
Because of how the tool was designed, plugins _should_ be expected to work out of the box if they followed the main patterns in place.
There is a list of already known issues in the Jenkins issue tracker, tracked through using the label `jcasc-incompatible` (link:https://issues.jenkins-ci.org/secure/Dashboard.jspa?selectPageId=17346[see dashboard]).
There is a list of already known issues in the Jenkins issue tracker, tracked through using the label `jcasc-incompatible` (link:https://issues.jenkins.io/secure/Dashboard.jspa?selectPageId=17346[see dashboard]).
This document is an *ongoing* community effort.
Hence a missing plugin here and has no existing issue filed in JIRA (see above) does not _necessarily_ mean it won't work.

View File

@ -19,6 +19,6 @@ Whenever you report a problem please provide information about:
1. Create a github issue for your feature/problem you want to solve
2. Implement solution on a branch in your fork
3. Make sure to include issue number in commit message, and make the message speak for itself
4. Once you're done create Pull Request and ask at least one of the maintainers for review (@ndeloof, @ewelinawilkosz)
4. Once you're done create a pull request and ask at least one of the maintainers for review (@ndeloof, @ewelinawilkosz)
!! Never push directly to this repository

View File

@ -1,70 +1,71 @@
# Jenkins Configuration as Code : implementation details
# Implementation Details
Input configuration file uses a YAML hierarchical data structure.
every node of this data structure is passed to a `Configurator` responsible
to apply the adequate configuration on Jenkins live instance.
The configuration file uses a YAML hierarchical data structure.
Every node of this data structure is passed to a `Configurator` responsible
to apply the adequate configuration on a Jenkins live instance.
## Configurator
A [`Configurator`](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/plugin/src/main/java/io/jenkins/plugins/casc/Configurator.java)
is managing a specific Jenkins Component, and as such knows
about data this component exposes to end-user for configuration.
is managing a specific Jenkins component, and as such knows
about data this component exposes to end users for configuration.
It has:
* a `name` to match a YAML entry,
* a `name` to match a YAML entry
* a `target` component type
* a `describe` method to document the attributes the target component exposes to configuration
* a `configure` method to configure the target component
From a yaml node with associated `Configurator`, configuration-as-code will handle every
child node in YAML structure based on current node's `Attribute`s, as described by the `Configurator`.
From a YAML node with an associated `Configurator`, configuration-as-code will handle every
child node in the YAML structure based on the current node's `Attribute`s, as described by the `Configurator`.
## Root Configurator selection
Root elements are identified by YAML entry name, and a matching
[`RootElementConfigurator`](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/plugin/src/main/java/io.jenkins/plugins/casc/RootElementConfigurator.java) is selected.
[`RootElementConfigurator`](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/plugin/src/main/java/io/jenkins/plugins/casc/RootElementConfigurator.java) is selected.
`RootElementConfigurator` is a special interface used to identify a `Configurator` which manages a top level
configuration element in the yaml document.
configuration element in the YAML document.
configuration-as-code do provide a custom `RootElementConfigurator` for `jenkins` root entry in yaml document,
configuration-as-code provides a custom `RootElementConfigurator` for the `jenkins` root entry in the YAML document,
as well as generic `RootElementConfigurator`s to model [global configuration categories](https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/jenkins/model/GlobalConfigurationCategory.java).
### Attributes
Configurator do document the target component by implementing `describe` method. This one do returl a set
of [`Attribute`](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/plugin/src/main/java/io.jenkins/plugins/casc/Attribute.java)s
`Configurator` documents the target component by implementing the `describe` method. This method returns a set
of [`Attribute`](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/plugin/src/main/java/io/jenkins/plugins/casc/Attribute.java)s
to document both name _AND_ type for a configurable attribute.
We don't want to expose the whole Jenkins Java API to configuration-as-code. Many components do define setter
methods for technical reasons or to support backward compatibility. So configuration-as-code do exclude :
We don't want to expose the whole Jenkins Java API to configuration-as-code. Many components define setter
methods for technical reasons or to support backward compatibility. So configuration-as-code excludes:
* setter methods marked as `@Deprecated`
* setter methods marked as `@Restricted`
Attribute also is responsible to document the target component type. We use Java reflexion to extract this
information from Java API, including parameterized types.
`Attribute` also is responsible to document the target component type. We use Java reflection to extract this
information from the Java API, including parameterized types.
As a resume, a component which exposes a method like :
As a resume, a component which exposes a method like:
```java
public void setFoo(List<Foo`> foos) { ... }
public void setFoo(List<Foo> foos) { ... }
```
will be detected as Attribute named `foo` with target type `Foo` with multiple values expected.
will be detected as attribute named `foo` with target type `Foo` with multiple values expected.
### Configuration
Configurator also has to implement the `configure` method to process yaml content and instantiate or configure
target component. The actual mechanism depends on the target. Configuration-as-Code do provide generic
Configurator also has to implement the `configure` method to process YAML content and instantiate or configure
the target component. The actual mechanism depends on the target. Configuration-as-Code provides generic
mechanisms which cover most Jenkins components.
This generic mechanism assumes Jenkins core components and plugins do follow some conventions, but
custom "glue-code" can also be provided as a (temporary) workaround, or to expose a configuration model
which doesn't reflect the internal data model, but better matches the end-user experience.
which doesn't reflect the internal data model, but better matches the end user experience.
A typical sample for this scenario is credentials-plugin.
[CredentialsRootConfigurator](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/plugin/src/main/java/io.jenkins/plugins/casc/credentials/CredentialsRootConfigurator.java)
do expose a simplified configuration API for `system` credentials store, which is hardly configurable
using the other general purpose configuration-as-code component due to internal design of this plugin.
A typical sample for this scenario is the [credentials](https://plugins.jenkins.io/credentials) plugin.
[CredentialsRootConfigurator](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/support/src/main/java/io/jenkins/plugins/casc/support/credentials/CredentialsRootConfigurator.java)
exposes a simplified configuration API for the `system` credentials store, which is hardly configurable
using the other general purpose configuration-as-code component due to the internal design of this plugin.
## General purpose configurators
@ -74,27 +75,27 @@ As we want to reflect web UI user experience, relying on the same configuration
UI is a natural approach.
`org.jenkinsci.plugins.casc.impl.configurators.DataBoundConfigurator` can configure arbitrary
jenkins component to rely on `DataBoundConstructor`
and `DataBoundSetter`s for UI data-binding. It uses same attributes names as
Jenkins components to rely on `DataBoundConstructor`
and `DataBoundSetter`s for UI data-binding. It uses the same attribute names as
the web UI, which are expected to be human friendly.
When, for some technical or legacy reasons, technical attribute name isn't user friendly, we also support
`@Symbol` annotation on setter to offer a better user-experience.
When, for technical or legacy reasons, the technical attribute name isn't user friendly, we also support
`@Symbol` annotation on setters to offer a better user experience.
### Descriptors
`org.jenkinsci.plugins.casc.DescriptorRootElementConfigurator` can configure
global configuration for Descriptors, to mimic the `global.jelly` UI exposed
to end user on the web UI.
to end users on the web UI.
Jenkins has hundreds Descriptors, most of them for internal technical reasons,
so only the ones to have a `global` view are accessible from configuration-as-code.
Jenkins has hundreds of Descriptors, most of them for internal technical reasons,
so only the ones that have a `global` view are accessible from configuration-as-code.
For Descriptors to work well with configuration-as-code, they need to follow
[some design best practices](PLUGINS.md) in terms of data binding. This is not such a common thing,
[some design best practices](docs/PLUGINS.md) in terms of data binding. This is not such a common thing,
so we expect this will require some evangelism on plugin developers.
As a short terms workaround, a custom `Configurator` glue-code implementation can be implemented.
As short term workaround, a custom `Configurator` glue-code implementation can be implemented.
## Initial secrets

View File

@ -19,7 +19,7 @@ Experienced Jenkins users rely on groovy init scripts to customize Jenkins and e
scripts directly invoke Jenkins API and as such can do everything (at your own risk). But they also require
you know Jenkins internals, and are confident in writing groovy scripts on top of Jenkins API.
Configuration-as-Code plugin has been designed as an _**opinionated**_ way to configure Jenkins based on
The configuration-as-code plugin has been designed as an _**opinionated**_ way to configure Jenkins based on
human-readable declarative configuration files. Writing such a file should be feasible without being a Jenkins
expert, just translating into _code_ a configuration process one is used to executing in the web UI.
@ -45,7 +45,7 @@ so end-users have full guidance in using this tool-set and do not have to search
## Getting Started
First, start a Jenkins instance with JCasC [plugin](https://plugins.jenkins.io/configuration-as-code) installed.
First, start a Jenkins instance with the [configuration-as-code](https://plugins.jenkins.io/configuration-as-code) plugin installed.
- Those running Jenkins as a [Docker container](https://github.com/jenkinsci/docker) (and maybe also [pre-installing plugins](https://github.com/jenkinsci/docker#preinstalling-plugins)), do include [configuration-as-code](https://plugins.jenkins.io/configuration-as-code) plugin and optionally the [configuration-as-code-support](https://plugins.jenkins.io/configuration-as-code-support) plugin if you use one of the credentials plugins or the job-dsl (see link).
@ -141,12 +141,12 @@ INFO: Jenkins is fully up and running
## Initial Configuration
When configuring the first Jenkins instance, browse the examples shown in the [demos](demos)
directory of this repository. If you have a plugin that do not have an example, consult the reference
directory of this repository. If you have a plugin that does not have an example, consult the reference
help document. Click the `Documentation` link at the bottom of the Configuration as Code page.
![Reference Page](images/reference.png)
If you might wish to configure a specific plugin, search the page for the name of the plugin. The page will
If you want to configure a specific plugin, search the page for the name of the plugin. The page will
show you which root element belongs to the configuration. Most installed plugins belong under the `unclassified` root
element.
@ -163,7 +163,7 @@ jenkins:
nodes:
- permanent:
name: "static-slave"
name: "static-agent"
remoteFS: "/home/jenkins"
launcher:
jnlp:
@ -201,18 +201,18 @@ Also see [demos](demos) folder with various samples.
The configuration file format depends on the version of jenkins-core and installed plugins.
Documentation is generated from a live instance, as well as a JSON-schema you can use to validate configuration file
with your favourite yaml tools.
with your favourite YAML tools.
## Handling Secrets
Currently, you can provide initial secrets to Configuration-as-Code that all rely on <key,value>
substitution of strings in configuration. For example, ``Jenkins: `${some_var}` ``. Default variable substitution
substitution of strings in the configuration. For example, ``Jenkins: `${some_var}` ``. Default variable substitution
using the `:-` operator from `bash` is also available. For example, `key: ${VALUE:-defaultvalue}` will evaluate to `defaultvalue` if `$VALUE` is unset. To escape a string from secret interpolation, put `^` in front of the value. For example, `Jenkins: ^${some_var}` will produce the literal `Jenkins: ${some_var}`.
We can provide these initial secrets in the following ways:
- Using environment variables.
- Using docker-secrets, where files on path `/run/secrets/${KEY}` will be replaced by `${KEY}` in configuration. The base folder `/run/secrets` can be overriden by setting the environment variable `SECRETS`. So this can be used as a file based secret, and not just docker secrets.
- Using docker-secrets, where files on path `/run/secrets/${KEY}` will be replaced by `${KEY}` in the configuration. The base folder `/run/secrets` can be overridden by setting the environment variable `SECRETS`. So this can be used as a file based secret, and not just docker secrets.
- Using Kubernetes secrets, logic is the same as for docker-secrets. The secret needs to be mounted as a file to `/run/secrets/`, and then the filename can be used as the KEY. For example:
```yaml
@ -242,7 +242,7 @@ Prerequisites:
- The environment variable `CASC_VAULT_PW` must be present, if token is not used and appRole/Secret is not used. (Vault password.)
- The environment variable `CASC_VAULT_USER` must be present, if token is not used and appRole/Secret is not used. (Vault username.)
- The environment variable `CASC_VAULT_APPROLE` must be present, if token is not used and U/P not used. (Vault AppRole ID.)
- The environment variable `CASC_VAULT_APPROLE_SECRET` must be present, it token is not used and U/P not used. (Value AppRole Secret ID.)
- The environment variable `CASC_VAULT_APPROLE_SECRET` must be present, it token is not used and U/P not used. (Vault AppRole Secret ID.)
- The environment variable `CASC_VAULT_TOKEN` must be present, if U/P is not used. (Vault token.)
- The environment variable `CASC_VAULT_PATHS` must be present. (Comma separated vault key paths. For example, `secret/jenkins,secret/admin`.)
- The environment variable `CASC_VAULT_URL` must be present. (Vault url, including port number.)
@ -253,7 +253,7 @@ Prerequisites:
If the environment variables `CASC_VAULT_URL` and `CASC_VAULT_PATHS` are present, Configuration-as-Code will try to gather initial secrets from Vault. However for it to work properly there is a need for authentication by either the combination of `CASC_VAULT_USER` and `CASC_VAULT_PW`, a `CASC_VAULT_TOKEN`, or the combination of `CASC_VAULT_APPROLE` and `CASC_VAULT_APPROLE_SECRET`. The authenticated user must have at least read access.
You can also provide a `CASC_VAULT_FILE` environment variable where you load the secrets from file.
You can also provide a `CASC_VAULT_FILE` environment variable where you load the secrets from a file.
File should be in a Java Properties format
@ -304,7 +304,7 @@ We currently do support plugin installation but it will remain in `beta` for the
we recommend that you package your plugins with your Jenkins distribution as plugin installation often requires a
restart and can cause problems with plugin dependencies. So if you want to try it, you can.
Current implementation do require a restart if you add a plugin.
The current implementation does require a restart if you add a plugin.
Example: (Requires Configuration as Code Plugin version > 0.7-alpha)
@ -317,10 +317,10 @@ plugins:
## Supported Plugins
Most plugins should be supported out-of-the-box, or maybe require some minimal changes. See this [dashboard](https://issues.jenkins-ci.org/secure/Dashboard.jspa?selectPageId=17346) for known compatibility issues.
Most plugins should be supported out-of-the-box, or maybe require some minimal changes. See this [dashboard](https://issues.jenkins.io/secure/Dashboard.jspa?selectPageId=17346) for known compatibility issues.
## Jenkins Enhancement Proposal
As Configuration-as-code is demonstrated to be a highly requested topic in Jenkins community, we have published
As configuration-as-code is demonstrated to be a highly requested topic in Jenkins community, we have published
[JEP 201](https://github.com/jenkinsci/jep/tree/master/jep/201) as proposal to make this a standard component
of the Jenkins project. The proposal was accepted. :tada:

View File

@ -22,6 +22,7 @@ unclassified:
```
## implementation note
Currently setting credentials causes ERROR & `Enable Push to Bintray` is not supported (always enabled).
see [https://www.jfrog.com/jira/browse/HAP-1018]

View File

@ -48,5 +48,3 @@ unclassified:
</activeProfiles>
</settings>
```

View File

@ -32,4 +32,3 @@ jenkins:
Jenkins singleton doesn't offer any `setClouds` method. So here we rely on a pseudo-property implemented by a dedicated
`Attribute` to add the configured clouds to `Jenkins.clouds`. The current implementation only adds the configured cloud
if it doesn't exists yet.

View File

@ -1,4 +1,4 @@
# configure Amazon EC2 Plguin
# configure Amazon EC2 Plugin
https://wiki.jenkins.io/display/JENKINS/Amazon+EC2+Plugin

View File

@ -14,12 +14,10 @@ tool:
## implementation note
Here we relies on `hudson.tools.ToolDescriptor.setInstallations`, so same applies to all ToolInstallations.
Unfortunately java reflection make it hack-ish to detect the parameter type of this method from derived concrete
Here we rely on `hudson.tools.ToolDescriptor.setInstallations`, so same applies to all ToolInstallations.
Unfortunately Java reflection makes it hack-ish to detect the parameter type of this method from derived concrete
class, so maybe there's some corner case we will need to polish this logic.
Also, Yaml lists are converted into `ArrayLists` but `setInstallations(T ... installation)` varags method require
and array - blame java to not just accept any `Iterable` - so we need to detect this scenario and do the type
Also, YAML lists are converted into `ArrayLists` but `setInstallations(T ... installation)` varags method require
an array - blame Java to not just accept any `Iterable` - so we need to detect this scenario and do the type
conversion.

View File

@ -25,5 +25,3 @@ unclassified:
readTimeout: 10
url: "https://gitlab.com/"
```

View File

@ -4,8 +4,7 @@ Basic Jenkins configuration under `Configure System`, which is not a part of any
Many of the plugins are actually configured in the same section, but to configure them you'll put their configuration under `unclassified` root element - details in plugin's specific subfolders.
[jenkins.yaml](jenkins.yaml) file is an example of configuration file with Jenkins and a number of plugins configured.
[jenkins.yaml](jenkins.yaml) file is an example of a configuration file with Jenkins and a number of plugins configured.
## sample configuration
@ -18,7 +17,8 @@ jenkins:
```
### Multiline system message
There are (too) many ways to write multi-line strings in yaml, but one of the most readable solutions
There are (too) many ways to write multi-line strings in YAML, but one of the most readable solutions
is to use the following syntax, that doesn't need escaped newlines and other shenanigans:
```yaml
@ -30,10 +30,11 @@ jenkins:
Config is now mostly handled by 'Jenkins Configuration as Code Plugin' (JCasC).
JCasC config can be found in the jenkins.yaml file in the $JENKINS_HOME/casc/ folder.
some settings are still injected from init.groovy.d scripts,
Some settings are still injected from init.groovy.d scripts,
but these settings will be ported over to JCasC as support becomes available.
numExecutors: 1 # This is just a random example entry to show that there is no "end token" for the multiline string apart from un-indent to the next yaml property.
numExecutors: 1 # This is just a random example entry to show that there is no "end token" for the multiline string apart from un-indent to the next YAML property.
```
# implementation note
Example above is only a subset of commonly used settings, full list available in generated documentation
The example above is only a subset of commonly used settings. The full list is available in the generated documentation.

View File

@ -4,20 +4,20 @@ As explained in [seed-jobs.md](../../docs/seed-jobs.md), `jobs` declaration is u
For now, it is using the [job-dsl-plugin](https://wiki.jenkins.io/display/JENKINS/Job+DSL+Plugin) so this plugin needs to be installed on your Jenkins instance for this sample to work.
Job-DSL plugin uses groovy syntax for it's job configuration DSL, so a mix of yaml and groovy must be used within the
The Job DSL plugin uses groovy syntax for its job configuration DSL, so a mix of YAML and groovy must be used within the
configuration-as-code file.
## sample configurations
[bitbucket.yaml](bitbucket.yaml) file is an example of configuration file with Jenkins and an Organization Folder Job Type with automatic branch discovering in Bitbucket. It requires [Branch API plugin](https://github.com/jenkinsci/branch-api-plugin) and [Bitbucket Branch Source plugin](https://github.com/jenkinsci/bitbucket-branch-source-plugin) to be able to run this demo. `$BITBUCKET_URL` is a system environment variable that needs to be defined before Jenkins is started.
[bitbucket.yaml](bitbucket.yaml) file is an example of a configuration file with Jenkins and an Organization Folder Job Type with automatic branch discovering in Bitbucket. It requires [Branch API plugin](https://github.com/jenkinsci/branch-api-plugin) and [Bitbucket Branch Source plugin](https://github.com/jenkinsci/bitbucket-branch-source-plugin) to be able to run this demo. `$BITBUCKET_URL` is a system environment variable that needs to be defined before Jenkins is started.
[pipeline.yaml](pipeline.yaml) file is an example of configuring a folder and a descrative pipeline job within that folder.
[pipeline.yaml](pipeline.yaml) file is an example of configuring a folder and a declarative pipeline job within that folder.
[multibranch-github.yaml](multibranch-github.yaml) file is an example of a multibranch pipeline job configured with GitHub as branch source, an orphaned item strategy and periodic scan triggers of 5 mins.
## implementation note
- The main issue in `jobs` declaration for now concerns the difference in 'Traits' declaration due to https://issues.jenkins-ci.org/browse/JENKINS-45504.
When is is resolved, the workaround using `configure` part will no longer be needed and all traits will be declared under the organizations section.
- The main issue with the `jobs` declaration for now is the difference in the 'Traits' declaration due to https://issues.jenkins.io/browse/JENKINS-45504.
When is is resolved, the workaround using the `configure` part will no longer be needed and all traits will be declared under the organizations section.
- JobDSL only allow 'periodic(int min)' for configuring trigger for now. So to configure "1 day" for example, we need to use the `configure` workaround as shown in [bitbucket.yaml](bitbucket.yaml#L68)
- Job DSL only allows 'periodic(int min)' for configuring trigger for now. So to configure "1 day" for example, we need to use the `configure` workaround as shown in [bitbucket.yaml](bitbucket.yaml#L68)

View File

@ -37,7 +37,7 @@ jobs:
// "Traits" ("Behaviours" in the GUI) that are NOT "declarative-compatible"
// For some 'traits, we need to configure this stuff by hand until JobDSL handles it
// https://issues.jenkins-ci.org/browse/JENKINS-45504
// https://issues.jenkins.io/browse/JENKINS-45504
configure { node ->
def traits = node / navigators / 'com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMNavigator' / traits
traits << 'com.cloudbees.jenkins.plugins.bitbucket.BranchDiscoveryTrait' {

View File

@ -18,4 +18,3 @@ unclassified:
"confidential-port": 0
}
```

View File

@ -2,10 +2,10 @@
## Preparation
Jenkins can be installed in Kubernetes using [`helm`](https://github.com/helm/helm).
The latest stable helm chart can be found [`here`](https://github.com/helm/charts/tree/master/stable/jenkins).
Jenkins can be installed in Kubernetes using [helm](https://github.com/helm/helm).
The latest stable helm chart can be found [here](https://github.com/helm/charts/tree/master/stable/jenkins).
Now grab a copy of the helm chart [`values file`](https://github.com/helm/charts/blob/master/stable/jenkins/values.yaml) and adjust the Master part a little bit:
Now grab a copy of the helm chart [values file](https://github.com/helm/charts/blob/master/stable/jenkins/values.yaml) and adjust the Master part a little bit:
```yaml
Master:
@ -23,9 +23,9 @@ Master:
# Below is the implementation of Jenkins Configuration as Code. Add a key under ConfigScripts for each configuration area,
# where each corresponds to a plugin or section of the UI. Each key (prior to | character) is just a label, and can be any value.
# Keys are only used to give the section a meaningful name. The only restriction is they may only contain RFC 1123 \ DNS label
# characters: lowercase letters, numbers, and hyphens. The keys become the name of a configuration yaml file on the master in
# characters: lowercase letters, numbers, and hyphens. The keys become the name of a configuration YAML file on the master in
# /var/jenkins_home/casc_configs (by default) and will be processed by the Configuration as Code Plugin. The lines after each |
# become the content of the configuration yaml file. The first line after this is a JCasC root element, eg jenkins, credentials,
# become the content of the configuration YAML file. The first line after this is a JCasC root element, eg jenkins, credentials,
# etc. Best reference is https://<jenkins_url>/configuration-as-code/reference. The example below creates a welcome message:
JCasC:
enabled: true
@ -77,7 +77,7 @@ Master:
value: /var/jenkins_home/casc_configs/..data/jenkins.yaml
# `SECRETS` is used to override the `/run/secrets` path,
# which is useful for setting credentials.
# But it needs to be used in conjuction with Master.SecretsFilesSecret
# But it needs to be used in conjunction with Master.SecretsFilesSecret
# - name: SECRETS
# value: /usr/share/jenkins/ref/secrets
@ -102,4 +102,4 @@ Once Helm finishes deploying the chart, connect to your Jenkins server in your b
## Misc
Check the [`Configuration as Code`](https://github.com/helm/charts/tree/master/stable/jenkins#configuration-as-code) section in the Jenkins Helm chart repo for more information.
Check the [Configuration as Code](https://github.com/helm/charts/tree/master/stable/jenkins#configuration-as-code) section in the Jenkins Helm chart repo for more information.

View File

@ -16,7 +16,7 @@ Master:
OwnSshKey: false
# If CasC auto-reload is enabled, an SSH (RSA) keypair is needed. Can either provide your own, or leave unconfigured\false to allow a random key to be auto-generated.
# If you choose to use your own, you must upload your decrypted RSA private key (not the public key above) to a Kubernetes secret using the following command:
# kubectl -n <namespace> create secret generic <helm_release_name> --dry-run --from-file=jenkins-admin-private-key=~/.ssh/id_rsa -o yaml |kubectl -n <namespace> apply -f -
# kubectl -n <namespace> create secret generic <helm_release_name> --dry-run --from-file=jenkins-admin-private-key=~/.ssh/id_rsa -o YAML |kubectl -n <namespace> apply -f -
# Replace ~/.ssh/id_rsa in the above command with the path to your private key file and the <helm_release_name> and <namespace> placeholders to suit.
resources:
requests:
@ -29,9 +29,9 @@ Master:
# Below is the implementation of Jenkins Configuration as Code. Add a key under ConfigScripts for each configuration area,
# where each corresponds to a plugin or section of the UI. Each key (prior to | character) is just a label, and can be any value.
# Keys are only used to give the section a meaningful name. The only restriction is they may only contain RFC 1123 \ DNS label
# characters: lowercase letters, numbers, and hyphens. The keys become the name of a configuration yaml file on the master in
# characters: lowercase letters, numbers, and hyphens. The keys become the name of a configuration YAML file on the master in
# /var/jenkins_home/casc_configs (by default) and will be processed by the Configuration as Code Plugin. The lines after each |
# become the content of the configuration yaml file. The first line after this is a JCasC root element, eg jenkins, credentials,
# become the content of the configuration YAML file. The first line after this is a JCasC root element, eg jenkins, credentials,
# etc. Best reference is https://<jenkins_url>/configuration-as-code/reference. The example below creates a welcome message:
JCasC:
enabled: true
@ -82,7 +82,7 @@ Master:
# requires additional JavaOpts, ie
# JavaOpts: >
# -Dcom.sun.management.jmxremote.port=4000
# -Dcom.sun.management.jmxremote.authenticsate=false
# -Dcom.sun.management.jmxremote.authenticate=false
# -Dcom.sun.management.jmxremote.ssl=false
# JMXPort: 4000
# List of plugins to be install during Jenkins master start

View File

@ -1,11 +1,13 @@
# Configure Kubernetes secrets for Jenkins configuration-as-code plugin
### Prerequisites
1. `SECRETS` environment variable should provide a path to mounted secret volume.
2. Kubernetes secrets with all required values.
3. `volumeMounts` and `volumes` directives of Kubernetes manifest should have records for Kubernetes secrets mounts.
### Sample configuration
```
---
apiVersion: v1

View File

@ -1,8 +1,8 @@
# Configure Kubernetes plugin
Jenkins can be installed in Kubernetes and preconfigured to run jobs (and other
options) in the Kubernetes cluster, using yaml stored in a `ConfigMap`.
See [`config.yml`](config.yml) for the `ConfigMap` definition.
options) in the Kubernetes cluster, using YAML stored in a `ConfigMap`.
See [config.yml](config.yml) for the `ConfigMap` definition.
Example installation on Kubernetes:
@ -65,4 +65,4 @@ jenkins:
idleMinutes: "1"
activeDeadlineSeconds: "120"
slaveConnectTimeout: "1000"
```
```

View File

@ -20,9 +20,9 @@ jenkins:
## implementation note
`hudson.security.LDAPSecurityRealm` can be configure using it's @DataBoundConstructor parameters without any dedicated
`hudson.security.LDAPSecurityRealm` can be configured using its `@DataBoundConstructor` parameters without any dedicated
adapter code.
It is identified as `ldap` as it implements `SecurityRealm` extension point, so we can define a "natural" Symbol name
It is identified as `ldap` as it implements the `SecurityRealm` extension point, so we can define a "natural" symbol name
for it.
## sample configuration with search filters

View File

@ -20,10 +20,10 @@ unclassified:
## implementation note
`hudson.task.Mailer.Descriptor` do expose global SMTP configuration parameters.
It is identified as yaml root element `mailer` as this descriptor has a `global.jelly` UI view, so configuration-as-code
assumes it make sense to expose it as a root element extension.
`hudson.task.Mailer.Descriptor` exposes global SMTP configuration parameters.
It is identified as YAML root element `mailer` as this descriptor has a `global.jelly` UI view, so configuration-as-code
assumes it makes sense to expose it as a root element extension.
Descriptor do define setters so we can inject configuration, but for SMTP authentication parameters.
Descriptor defines setters so we can inject configuration, but for SMTP authentication parameters.
See https://github.com/jenkinsci/configuration-as-code-plugin/issues/2.
See https://github.com/jenkinsci/mailer-plugin/pull/39

View File

@ -1,11 +1,11 @@
# configure installed plugins
Configuration-as-Code can manage plugin installation, assuming Configuration-as-Code-plugin is
intiialy installed (chicken & egg ... ) !
initially installed (chicken & egg ... )!
yaml configuration can declare a set of required plugins and version. We require
a version as primary goal is to ensure reproducibility, but we also support `latest`
as a version number for your conveninence.
YAML configuration can declare a set of required plugins and version. We require
a version as the primary goal is to ensure reproducibility, but we also support `latest`
as version number for your convenience.
For plugins not hosted on an update center, you can set a download URL as version.
@ -19,13 +19,11 @@ plugins:
my-custom-plugin: http://download.acme.com/my-custom-plugin-1.0.jpi
```
## implementation note
Plugin installation with specific version require update center to expose
metadata per hosted plugins version, not just latest.
Plugin installation with a specific version requires an update center to expose
metadata per hosted plugin version, not just latest.
Jenkins community update center expose [`plugin-versions.json`](https://updates.jenkins.io/current/plugin-versions.json)
Jenkins community update center exposes [`plugin-versions.json`](https://updates.jenkins.io/current/plugin-versions.json)
metadata file. Proprietary update centers might not, in such case you will have
to use download URLs in your yaml file.
to use download URLs in your YAML file.

View File

@ -1,7 +1,7 @@
# role-strategy-plugin
<https://plugins.jenkins.io/role-strategy>
Basic configuration of the [Role-based Authorization Strategy plugin](https://plugins.jenkins.io/role-strategy)
## sample
Check out the example yaml file [role-strategy-auth.yaml] which is taken from the plugins' integration test resources <https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/integrations/src/test/resources/io/jenkins/plugins/casc/RoleStrategy1.yml>
Check out the example YAML file [role-strategy-auth.yaml] which is taken from the plugins' integration test resources <https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/integrations/src/test/resources/io/jenkins/plugins/casc/RoleStrategy1.yml>

View File

@ -1,18 +1,18 @@
# configure sonar plugin
## sample configuration
Sample configuration for the SonarQube plugin
```yaml
jenkins:
[...]
unclassified:
sonarglobalconfiguration: # mandatory
buildWrapperEnabled: true
installations: # mandatory
- name: sonarqube # id of the SonarQube configuration - to be used in jobs
- name: sonarqube # id of the SonarQube configuration - to be used in jobs
serverUrl: http://sonarqube-service:9000/sq
additionalAnalysisProperties:
additionalProperties:
@ -20,4 +20,5 @@ unclassified:
```
## notes
You can add multiple installations.

View File

@ -1,6 +1,7 @@
# configure statistics-gatherer plugin
## sample configuration
Sample configuration for the Statistics Gatherer plugin.
```yaml
@ -16,4 +17,4 @@ unclassified:
projectInfo: false
buildStepInfo: false
scmCheckoutInfo: true
```
```

View File

@ -20,4 +20,4 @@ unclassified:
## implementation note
User account name mapping strategy is not yet supported
User account name mapping strategy is not yet supported.

View File

@ -23,8 +23,3 @@ unclassified:
return builder.buildOptional();
example: "somefile.txt:2:SeriousWarnings:SomethingWentWrong"
```

View File

@ -10,12 +10,12 @@ jenkins:
unclassified:
globalLibraries:
libraries:
- name: "awesome-lib"
- name: 'awesome-lib'
retriever:
modernSCM:
scm:
git:
remote: "https://github.com/jenkins-infra/pipeline-library.git"
remote: 'https://github.com/jenkins-infra/pipeline-library.git'
```
## Using credentials

View File

@ -1,6 +1,6 @@
# Developer's documentation
This document describe Configuration-as-Code API and design for plugin developer who are interested in
This document describe Configuration-as-Code API and design for plugin developer who are interested in
extending Configuration-as-Code by implementing custom Configurators or re-using the configuration mechanism
in another context.
@ -9,35 +9,33 @@ in another context.
## Configurators
Third party code to rely on Configuration as Code has to create a key:value hierarchical representation of the target
component and it's sub-components. This representation is defined by the `io.jenkins.plugins.casc.model` package,
and does not force use on any specific file format, despite we focus on `yaml` for Configuration-as-Code.
component and it's sub-components. This representation is defined by the `io.jenkins.plugins.casc.model` package,
and does not force use on any specific file format, despite we focus on `yaml` for Configuration-as-Code.
The main API is `Configurator` which encapsulate access to target component data model and how to create/configure it.
Such a data-model is exposed to external usage as a set of `Attribute`s via the `Configurator.describe()` method.
Each key in the key:value representation used as configuration input has to match an Attribute.
Each key in the key:value representation used as configuration input has to match an Attribute.
## ConfigurationContext
The configuration process only relies on `ConfigurationContext` to convert key:value representation into a live
component instance. Third party component to use this mechanism can provide a custom context, while
The configuration process only relies on `ConfigurationContext` to convert key:value representation into a live
component instance. Third party component to use this mechanism can provide a custom context, while
Configuration-as-Code do rely on registered Jenkins components.
ConfigurationContext do provide :
- tweaks support for deprecated and restricted attributes, as well as unknown input elements
- define registry to retrieve Configurator for various component and classes to be configured
- offer option to register `Listener`s to get notified about the configuration process and react on errors.
## Yaml support
## YAML support
`io.jenkins.plugins.casc.yaml` package do define the implementation for loading configuration from Yaml sources.
`YamlUtils.loadFrom` encapsulate the yaml parsing and merge process from a set of yaml documents, while `YamlSource`
`io.jenkins.plugins.casc.yaml` package do define the implementation for loading configuration from YAML sources.
`YamlUtils.loadFrom` encapsulate the YAML parsing and merge process from a set of YAML documents, while `YamlSource`
abstract the way we load documents from files, url, or any other sources.
# Extending Configuration-as-Code
`Configurator` and `Attribute` are the core abstraction of Configuration-as-Code to offer implementation flexibility.
Configuration-as-Code do offer implementation based on introspecting Java classes, relying on web UI data-binding
mechanisms for DataBound component, and on Java Bean conventions for others (Descriptors, Extensions).
@ -47,8 +45,6 @@ model without relying on introspection, one can extend `BaseConfigurator` and ov
control the exposed data model.
`Attribute`s exposed by this data model only have to define how to set value on target component and how to retrieve
current value from a live instance (used by `export` feature). Here again Configuration-as-Code do offer as default
current value from a live instance (used by `export` feature). Here again Configuration-as-Code do offer as default
implementation a Java Bean compliant implementation, but one could override get and/or set operation with custom
code to support alternate mechanisms.

View File

@ -1,16 +1,16 @@
# Guide to plugin developers
Configuration as Code relies on `Describable` and `DataBound` mechanism Jenkins plugin developers are probably already using.
As long as you follow [best practices](https://jenkins.io/doc/developer/plugin-development/pipeline-integration/#constructor-vs-setters)
Configuration as Code relies on `Describable` and `DataBound` mechanism Jenkins plugin developers are probably already using.
As long as you follow [best practices](https://jenkins.io/doc/developer/plugin-development/pipeline-integration/#constructor-vs-setters)
using those annotations for data-binding, same attributes will be usable for configuration-as-code.
## Descriptors global configuration
Most of the interesting plugin's configuration you want to expose to end users with configuration-as-code is managed by your plugin's
Most of the interesting plugin's configuration you want to expose to end users with configuration-as-code is managed by your plugin's
Descriptor(s) and exposed on web UI with a `global.jelly` view. This is fully supported by configuration-as-code as long as you rely on
the exact same `DataBound` mechanism, which isn't a common practice (yet).
In many plugins, `Descriptor#configure()` is implemented by lookup for attributes values from the `JSONObject`. To make your Descriptor
In many plugins, `Descriptor#configure()` is implemented by lookup for attributes values from the `JSONObject`. To make your Descriptor
compliant with configuration-as-code, you'll need to expose your configuration attributes as `@DataBoundSetters`.
Before you start, make sure the following pre-conditions are met :
@ -34,17 +34,16 @@ Before you start, make sure the following pre-conditions are met :
Here's the recommended approach :
Let's consider this Descriptor :
```java
```java
public static final class DescriptorImpl extends Descriptor<Foo> {
private String charset;
/** optional password */
private Secret password;
public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
charset = json.getString("charset");
if (json.has("usePassword")) {
password = Secret.fromString(nullify(auth.getString("password")));
@ -57,14 +56,15 @@ public static final class DescriptorImpl extends Descriptor<Foo> {
public String getCharset() { return charset; }
}
```
```
with global.jelly view :
```xml
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:entry title="${%Charset}" field="charset">
<f:textbox />
</f:entry>
</f:entry>
<f:optionalBlock name="usePassword" title="${%Use Authentication}" checked="${descriptor.password!=null}">
<f:entry title="${%Password}" field="password">
@ -76,18 +76,19 @@ with global.jelly view :
### Step 1
Define `@DataBoundSetters` javabean setters for your Descriptor's properties. They should match the getters you already have for
Define `@DataBoundSetters` javabean setters for your Descriptor's properties. They should match the getters you already have for
global.jelly data-binding.
```java
```java
@DataBoundSetter
public void setCharset(String charset) {
this.charset = charset;
}
```
### Step 2
Create a new Describable object with a `config.jelly` view to own optional attributes.
}
```
### Step 2
Create a new `Describable` object with a `config.jelly` view to own optional attributes.
```java
public class Authentication extends AbstractDescribableImpl<PAuthentication> {
@ -104,6 +105,7 @@ public class Authentication extends AbstractDescribableImpl<PAuthentication> {
}
}
```
```xml
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:entry title="${%Password}" field="smtpAuthPassword">
@ -113,31 +115,32 @@ public class Authentication extends AbstractDescribableImpl<PAuthentication> {
```
### Step 3
Define a new attribute in your Descriptor to own optional attributes.
For binary compatibility you'll need to maintain the legacy getters as delegates to this new sub-component.
For backward compatibility, use `readResolve` method to create the new nested component from legacy attributes.
```java
Define a new attribute in your Descriptor to own optional attributes.
For binary compatibility you'll need to maintain the legacy getters as delegates to this new sub-component.
For backward compatibility, use `readResolve` method to create the new nested component from legacy attributes.
```java
public static final class DescriptorImpl extends Descriptor<FooBar> {
private String charset;
/** @deprecated use {@link #authentication} */
private transient Secret password;
@CheckForNull
private Authentication authentication;
// --- backward compatibility
/** @deprecated use {@link #getAuthentication()} */
/** @deprecated use {@link #getAuthentication()} */
public Secret getPassword() { return authentication != null ? authentication.getPassword() : null; }
private Object readResolve() {
if (this.password != null) {
this.authentication = new Authentication(password);
}
return this;
}
}
```
### Step 4
@ -146,22 +149,22 @@ Replace `optionalBlocks` in your jelly view with `optionalProperty` and add the
```xml
<f:entry title="${%Charset}" field="charset">
<f:textbox />
</f:entry>
</f:entry>
<f:optionalProperty title="${%Use Authentication}" field="authentication"/>
```
```java
public Authentication getAuthentication() { return this.authentication; }
public Authentication getAuthentication() { return this.authentication; }
@DataBoundSetter
public void setAuthentication(Authentication authentication) { this.authentication = authentication; }
public void setAuthentication(Authentication authentication) { this.authentication = authentication; }
```
### Step 5
Rewrite `Descriptor#configure()` implementation to rely on `request.bindJson(this, json)`. You will have to reset attributes to their
default values as a Desciptor is a mutable object, i.e. data-binding won't reset values if they are not present in JSON payload.
default values as a Descriptor is a mutable object, i.e. data-binding won't reset values if they are not present in the JSON payload.
```java
public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
@ -174,30 +177,31 @@ default values as a Desciptor is a mutable object, i.e. data-binding won't reset
```
### Step 6
If you don't have one already, define a `@Symbol` annotation on your descriptor. This is the name end-user will be able to use to access
your Descriptor for configuration. To avoid collisions with other plugin, prefer using your plugin's artifactId as a symbolic name for your
If you don't have one already, define a `@Symbol` annotation on your descriptor. This is the name an end user will be able to use to access
your Descriptor for configuration. To avoid collisions with other plugins, prefer using your plugin's artifactId as a symbolic name for your
descriptor.
```java
```java
@Symbol("foo")
public static final class DescriptorImpl extends Descriptor<Foo> {
```
See [mailer plugin#39](https://github.com/jenkinsci/mailer-plugin/pull/39) for a sample on required changes.
## How to test?
## How to test ?
Simplest option for you to test JCasC compatibility in your plugin is to introduce a simple test-case.
Simplest option for you to test JCasC compatibility in your plugin is to introduce a simple test case.
### Configuration test
Add configuration-as-code-plugin as a test dependency in your pom.xml:
```xml
<dependency>
<groupId>io.jenkins</groupId>
<artifactId>configuration-as-code</artifactId>
<version>1.5</version>
<scope>test</scope>
<groupId>io.jenkins</groupId>
<artifactId>configuration-as-code</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
```
@ -225,28 +229,33 @@ Doing so, you will confirm JCasC is able to introspect your plugin and build the
some changes made to your plugin break this configuration model.
### Backward compatibility test
About the later, in case you need to introduce some breaking changes, you can define a backward-compatibility test case
About the later, in case you need to introduce some breaking changes, you can define a backward compatibility test case
```yaml
@Test public void should_be_backward_compatible() throws Exception {
ConfigurationAsCode.get().configure(ConfigAsCodeTest.class.getResource("obsolete-configuration-as-code.yml").toString());
assertTrue( /* check plugin has been configured as expected */ );
}
```
Within this `obsolete-configuration-as-code.yml` configuration file, use the legacy data model in use before the change you introduced, and enable JCasC support for deprecated methods:
```yaml
configuration-as-code:
deprecated: warn
```
This will let JCasC consider any `@Deprecated` setter in your component as a valid attribute to be set, enabling backward compatibility,
while the canonical JCasC model evolves to match the changes you made.
### Model export test
You also can write a test case to check export from a live instance is well supported :
```java
You also can write a test case to check export from a live instance is well supported:
```java
@Test public void export_configuration() throws Exception {
/* Setup jenkins to use plugin */
ConfigurationAsCode.get().export(System.out);
}
```
**TODO** we need to provide some yaml assertion library so that the resulting exported yam stream can be checked for expected content.
**TODO** we need to provide some yaml assertion library so that the resulting exported yam stream can be checked for expected content.

View File

@ -5,6 +5,7 @@
0.1-alpha version of Configuration as Code Plugin has a number of issues that may break your Jenkins instance - details below. DO NOT USE in production environment, only for test.
### Features available:
- Configure (some) plugins via yaml file
- Reload configuration from yaml file - manual step, available under `Manage Jenkins`:arrow_right: `Configuration as Code`
- Vault support - details in [README](../README.md)
@ -14,12 +15,13 @@
- Matrix (and Matrix Project) Authorization Strategy support
### Limitations:
- Location of yaml file with configuration MUST be provided via environment variable CASC_JENKINS_CONFIG - can be location on disk readable from Jenkins perspective
- plugins has to be installed manually (and it must happen before you try to configure them)
### How to use it
1. Add experimental plugins repository ([link](http://updates.jenkins-ci.org/experimental/update-center.json))
1. Add the experimental plugins repository ([link](http://updates.jenkins.io/experimental/update-center.json))
2. Prepare jenkins.yaml and store the location in CASC_JENKINS_CONFIG environment variable
3. Install *Configuration as Code* plugin (& all the others plugins you want to use)
4. When installed plugin will look for configuration file and configure Jenkins accordingly

View File

@ -1,40 +1,38 @@
# JCasC Requirements - guide for plugin maintainers
JCasC is designed so any plugin can be managed without the need to implement any custom
API, but still require plugins to respect some contract, aka "_convention over extension_".
API, but still require plugins to respect some contract, aka "_convention over extension_".
This documentation is here to explain plugin maintainers those conventions and provide guidance
on expected design.
![CasC is comming](BraceYourselves.jpg)
![CasC is coming](BraceYourselves.jpg)
## Overview
JCasC relies on ability to introspect jenkins configurable components to build a "data model"
from a live jenkins instance. For this purpose it relies on web UI data-binding conventions.
JCasC relies on the ability to introspect Jenkins configurable components to build a "data model"
from a live Jenkins instance. For this purpose it relies on web UI data-binding conventions.
For legacy reasons, Jenkins do offer multiple ways to support UI data-binding, but the sole
For legacy reasons, Jenkins offers multiple ways to support UI data-binding, but the sole
one to be introspection friendly is to offer `@DataBoundSetter` fields or setters in your code.
Surprisingly, this is well adopted by most plugins for `Describable` components, but not for
`Descriptor`s, despite the exact same mechanism can be used for both. And unfortunately, in
many case the interesting components to offer configuration one want to expose to JCasC
many cases the interesting components to offer configuration one want to expose to JCasC
is attached to a Descriptors.
## Check-list
### Rule 1: don't write code for data-binding
Check implementation of `Descriptor#configure(StaplerRequest,JSONObject)` in your descriptors.
This one should **not** use any of the `JSONObject.get*()` methods to set value for an internal
field. Prefer exposing javabean setter methods, and use `req.bindJSON(this,JSONObject)` to rely
This one should **not** use any of the `JSONObject.get*()` methods to set value for an internal
field. Prefer exposing javabean setter methods, and use `req.bindJSON(this,JSONObject)` to rely
on introspection-friendly data-binding.
Within a Descriptor such setters don't have to be annotated as `@DataBoundSetter` but we suggest
to do anyway, as it make it clear about the intent for such public methods.
Within a Descriptor such setters don't have to be annotated as `@DataBoundSetter` but we suggest
to do anyway, as it makes their intent more clear.
sample :
sample:
```java
public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
@ -46,7 +44,7 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti
}
```
to be replaced by :
to be replaced by:
```java
public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
@ -70,28 +68,28 @@ public void setReplyToAddress(String address) {
}
```
notes:
- you also need matching getters for jelly view to render current value, but you probably already have them declared.
- use of BulkChange allows to avoid repeated calls to `save()` to actually persist to disk only once fully
configured.
- you might not even need to implement `configure` once [#3669](https://github.com/jenkinsci/jenkins/pull/3669)
Notes:
- You also need matching getters for jelly view to render current value, but you probably already have them declared.
- Use of BulkChange allows to avoid repeated calls to `save()` to actually persist to disk only once fully
configured.
- You might not even need to implement `configure` once [#3669](https://github.com/jenkinsci/jenkins/pull/3669)
is merged.
### Rule 2: don't use pseudo-properties for optional
You might have a set of fields which only make sense when set altogether, and have jelly view
to use `<f:optionalBlock>` based on some boolean pseudo-property to show/hidde the matching section
to use `<f:optionalBlock>` based on some boolean pseudo-property to show/hide the matching section
in web UI.
Doing so require had-written data-binding code, so based on rule 1 should be prohibited.
Doing so requires had-written data-binding code, so based on rule 1 should be prohibited.
Hopefully there's a simple (and arguably better) way to handle this, by just using nested components
and group all related fields into an optional sub-element.
sample :
sample:
```xml
<f:optionalBlock name="useAuth" title="${%Use Authentication}"
<f:optionalBlock name="useAuth" title="${%Use Authentication}"
checked="${descriptor.username!=null}">
<f:entry title="${%User Name}" field="username">
<f:textbox />
@ -111,8 +109,8 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti
}
}
```
to be replaced by :
to be replaced by:
```xml
<f:optionalProperty field="Authentication" title="${%Use Authentication}"/>
@ -125,24 +123,24 @@ private Authentication authentication;
With a fresh new `Authentication` Describable class to host `username` and `password`, all
the `<f:optionalBlock>` body being moved `Authentication/config.jelly` view.
note: this also require some data migration logic, please read [PLUGINS](PLUGINS.md) for a step
Note: This also requires some data migration logic, please read [PLUGINS](PLUGINS.md) for a step
by step migration guide.
### Rule 3: define a test case if you can
Checking support for JCasC is easy as long as your plugin required java 8 / jenkins 2.60+.
Checking support for JCasC is easy as long as your plugin requires Java 8 / Jenkins 2.60+.
You just need CasC as a test dependency and a sample yaml file for your component
```xml
<dependency>
<groupId>io.jenkins</groupId>
<artifactId>configuration-as-code</artifactId>
<version>1.0</version>
<scope>test</scope>
<groupId>io.jenkins</groupId>
<artifactId>configuration-as-code</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
```
```java
public class ConfigAsCodeTest {
@ -153,15 +151,14 @@ public class ConfigAsCodeTest {
assertTrue( /* check plugin has been configured as expected */ );
}
```
Benefits for you to write such a testcase :
- You confirm your plugin is well design regarding JCasC conventions
Benefits for you to write such a test case:
- You confirm your plugin is well designed regarding JCasC conventions
- You offer users a sample configuration file
- You will be able to detect breaking changes that may impact your users
### Rule 4: ping us in case of doubts
Really, if you need any assistance getting your plugin to support JCasC, want code review
or anything, ping us on [Gitter](https://gitter.im/jenkinsci/configuration-as-code-plugin).
or anything, ping us on [Gitter](https://gitter.im/jenkinsci/configuration-as-code-plugin).

View File

@ -4,14 +4,14 @@
- An instance of [Hashicorps Vault](https://www.vaultproject.io/) running
- Using a docker-based approach is described [here](vault/setup-vault-using-docker.md)
- A Token (or Username and Password) as credentials for accessing Vault
- A token (or username and password) as credentials for accessing Vault
## Put stuff into Vault
Creating content in Vault can be done either using curl (not recommended) or using Vault as a client.
A simple curl example can be found [here](vault/setup-vault-using-docker.md). Use a native vault application whenever possible. They are available for download [here](https://www.vaultproject.io/downloads.html). Using vault via docker requires you to be inside a running vault docker container. Otherwise the steps are the same.
The below example assume that you have the following environment variables:
The below example assumes that you have the following environment variables:
- `$VAULT_TOKEN` containing the token to use as access credentials
- `$VAULT_SERVER_URL` containing the URL to your vault server, i.e. `http://vault.domain.local:8200`
@ -29,7 +29,7 @@ SSH_PRIVATE_KEY=@/vault/file/secrets/jenkins_ssh_key
Essentially, anything can go into a vault, as long as it's KEY=VALUE formatted. If you work inside a docker container, the above example requires you to have the file `/vault/file/secrets/jenkins_ssh_key` exist inside the docker container.
## Usage
## Usage
```bash
$ vault kv get kv/jenkins/master
@ -56,7 +56,5 @@ credentials:
## Current limitations
Due to dependency on BetterCloud's [vault-java-driver](https://github.com/BetterCloud/vault-java-driver), Vault's change default KV backend from v1 to v2 and HTTP endpoints change it's currently unable to use Vault's KV v2 secret store. ([see issue on BetterCloud project](https://github.com/BetterCloud/vault-java-driver/issues/114))
Due to the dependency on BetterCloud's [vault-java-driver](https://github.com/BetterCloud/vault-java-driver), Vault's change default KV backend from v1 to v2 and HTTP endpoints change it's currently unable to use Vault's KV v2 secret store. ([see issue on BetterCloud project](https://github.com/BetterCloud/vault-java-driver/issues/114))
Be aware which version you use as default dev Vault server, starting from 0.10, it uses KV v2. [See docs](https://www.vaultproject.io/docs/secrets/kv/kv-v2.html)

View File

@ -16,4 +16,4 @@ Various samples of plugins' configuration can be found in [demos](../demos) fold
## Export existing configuration
To be able to do that you need to install the plugin manually on your working Jenkins instance and use export function under http://[your_jenkins_url]/configuration-as-code/. Please note that export is not intended to offer a directly usable jenkins.yaml configuration. It can be used for inspiration writting your own, but be aware that export can be partial, or fail for some components.
To be able to do that, you need to install the plugin manually on your working Jenkins instance and use the export function under http://[your_jenkins_url]/configuration-as-code/. Please note that export is not intended to offer a directly usable jenkins.yaml configuration. It can be used for inspiration writing your own, but be aware that export can be partial, or fail for some components.

View File

@ -1,6 +1,6 @@
# How to create initial "seed" job
Configuration is not just about setting up jenkins master, it's also about creating an initial set of jobs.
Configuration is not just about setting up Jenkins master, it's also about creating an initial set of jobs.
For this purpose, we delegate to the popular [job-dsl-plugin](https://wiki.jenkins.io/display/JENKINS/Job+DSL+Plugin)
and run a job-dsl script to create an initial set of jobs.
@ -10,7 +10,7 @@ Typical usage is to rely on a multi-branch, or organization folder job type, so
created. So a multi-branch seed job will prepare a master to be fully configured for CI/CD targeting a repository
or organization.
Job-DSL plugin uses groovy syntax for it's job configuration DSL, so you'll have to mix yaml and groovy within your
Job-DSL plugin uses groovy syntax for its job configuration DSL, so you'll have to mix YAML and groovy within your
configuration-as-code file:
```yaml

View File

@ -6,66 +6,60 @@ It's based on some real customer cases and potential users we already have plans
In the early stage of the project, we use the scenarios to detect the most important missing features. Later we will use the scenarios as documentation and guidance on how to adapt the configuration as code approach.
## Manage and version control Jenkins global configuration
A small group of devops engineers are maintaining the company's Jenkins installations. There are a handful of Jenkins master's, an a few hundred slaves.
In general the devops team have full access to all the relevant infrastructure and are responsible for the documentation, compliance, maintenance and continued operation.
A small group of devops engineers are maintaining the company's Jenkins installations. There are a handful of Jenkins masters, and a few hundred agents.
In general the devops team has full access to all the relevant infrastructure and is responsible for the documentation, compliance, maintenance and continued operation.
From their IT department they are supplied with base server or client installations for servers and clients, and they apply configuration management practices to maintain the infrastructure.
For their Jenkins masters the only configuration not under version control is the Jenkins global configuration. The devops engineers maintain that, together with a set of trusted lead developers.
Their global configuration is most frequently changes related to (in order of most changed first): slave configuration, Jenkins plug-in updates, Jenkins global configuration changes.
All their Jenkins master have common pieces in common (e.g. Artifactory plugin configuration or mail setup) and some instance specific configuration because not all masters are used for the same kind of software development so plug-ins differs.
Their global configuration is most frequently changed related to (in order of most changed first): agent configuration, Jenkins plug-in updates, Jenkins global configuration changes.
All their Jenkins masters have pieces in common (e.g. Artifactory plugin configuration or mail setup) and some instance specific configuration because not all masters are used for the same kind of software development, so plug-ins differ.
In general the devops team agree that the running instances serves as documentation of the configuration themselves - one can always look in the UI. And they can restore from backup.
In general the devops team agrees that the running instances serve as documentation of the configuration themselves - one can always look in the UI. And they can restore from backup.
Their problems are always related to changes, where they update a plug-in or change a global configuration that gives unexpected side-effects and is rather hard to debug for the users or devops team members that do not know about it.
They try to remember to ping each other on their chat to inform about changes.
The devops team would like more traceability around changes, by completely move to manage the Jenkins global configuration as code and put it under version control. They will like to benefit also from having it as code to be able to spin up test environments and re-use common configuration across instances.
The devops team would like more traceability around changes, by completely moving to manage the Jenkins global configuration as code and put it under version control. They will like to benefit also from having it as code to be able to spin up test environments and re-use common configuration across instances.
**With Jenkins Configuration as Code plug-in** installed on their master, the devops team will describe all the configuration in the `jenkins.yml` and maintain it through a git repository. When-ever they want to change anything, they will edit the file in git and their production server will refresh the configuration or the list of installed plugi-ns.
**With Jenkins Configuration as Code plug-in** installed on their master, the devops team will describe all the configuration in the `jenkins.yml` and maintain it through a git repository. Whenever they want to change anything, they will edit the file in git and their production server will refresh the configuration or the list of installed plug-ins.
From that point on they all have full traceability of all the changes made, and they are able to roll it back easily by reverting commits. They can review the changes simply by looking at the git diffs on commits.
**Getting there and adopting Jenkins Configuration as Code** is also quite easy for the devops team. They will need to install the plug-in, and go the the Configuration as Code menu in Manage Jenkins, and use the export function to create the initial YAML files that represent their current global configuration and plug-in's installed. Export is not intended to offer a directly usable jenkins.yaml configuration. It can be used for inspiration writting your own, but be aware that export can be partial, or fail for some components.
When the files are in git, they can point to the file in the repository in the Configuration as Code menu, and click reload so Jenkins updates it's configuration accordingly.
**Getting there and adopting Jenkins Configuration as Code** is also quite easy for the devops team. They will need to install the plug-in, and go the the Configuration as Code menu in Manage Jenkins, and use the export function to create the initial YAML files that represent their current global configuration and plug-in's installed. Export is not intended to offer a directly usable jenkins.yaml configuration. It can be used for inspiration writing your own, but be aware that export can be partial, or fail for some components.
When the files are in git, they can point to the file in the repository in the Configuration as Code menu, and click reload so Jenkins updates its configuration accordingly.
_Migration step-by-step guide:_ For the exact steps, see this part of the migration guide - TBD when all relevant issues fixed:
* [#6 about reloading configuration when changed](https://github.com/jenkinsci/configuration-as-code-plugin/issues/6)
* [#7 about plug-in installation support](https://github.com/jenkinsci/configuration-as-code-plugin/issues/7)
* [#10 related to hierarchy and re-use of configuration](https://github.com/jenkinsci/configuration-as-code-plugin/issues/10)
* [#32 where to draft a migration to Jenkins Configuration as Code guide](https://github.com/jenkinsci/configuration-as-code-plugin/issues/32)
* [#65 helping users migrate by export existing configuration](https://github.com/jenkinsci/configuration-as-code-plugin/issues/65)
* [#6 about reloading configuration when changed](https://github.com/jenkinsci/configuration-as-code-plugin/issues/6)
* [#7 about plug-in installation support](https://github.com/jenkinsci/configuration-as-code-plugin/issues/7)
* [#10 related to hierarchy and re-use of configuration](https://github.com/jenkinsci/configuration-as-code-plugin/issues/10)
* [#32 where to draft a migration to Jenkins Configuration as Code guide](https://github.com/jenkinsci/configuration-as-code-plugin/issues/32)
* [#65 helping users migrate by export existing configuration](https://github.com/jenkinsci/configuration-as-code-plugin/issues/65)
## Jenkins master already in docker
A small full stack developer team have their single Jenkins master running in a container and they orchestrate and deploy it using one of the many container orchestration tools.
A small full stack developer team has their single Jenkins master running in a container and they orchestrate and deploy it using one of the many container orchestration tools.
Their Jenkins global configuration is the only piece not under version control, so they depend on the current data in `JENKINS_HOME` to persist the Jenkins global configuration and be able to redeploy the Jenkins master with existing installed plug-ins. They do not care about their historic build data.
**With Jenkins configuration as code plug-in** they can get their missing configuration under version control as well and their installed plug-in combinations and for this little full stack developer team it means they can always just redeploy their Jenkins should something be wrong or failing, and their container orchestration tool will keep their Jenkins master always running for them completely automatically.
**With Jenkins Configuration as Code plug-in** they can get their missing configuration under version control as well and their installed plug-in combinations and for this little full stack developer team it means they can always just redeploy their Jenkins, should something be wrong or failing, and their container orchestration tool will keep their Jenkins master always running for them completely automatically.
**Migrating to use the Jenkins Configuration as Code plug-in** is easy if they can live with doing just few manual steps before it is all automated. They need to install the Jenkins Configuration as Code plug-in on their current master, then use the export functionality to create the `plugins.yml` and `jenkins.yml` file for them, which they need to add to a git repository.
Then the last thing they need to do is to update their deployment recipe to use the customized Jenkins where the Jenkins Configuration as Code plug-in comes pre-installed, and have the recipe pass the URI to the `jenkins.yml` file when starting Jenkins.
After that they only do changes in the configuration file through git, and Jenkins Configuration as Code will refresh global configuration. Should their infrastructure fail their orchestration tool will recreate their master from scratch, but still with the same configuration and without depending on old data sets.
Notice a slight difference between `plugins.yml` as part of the Configuration as Code vs `plugins.txt` known from the Jenkins container setups. The latter one will need to contain all plugins and their dependencies and will usually be auto generated to support starting a Jenkins container with all the plug-ins one like. The `plugin.yml` takes the approach of only mentioning the plugin and their version (or latest) the user really cares about, and Configuration as Code will resolve dependencies for the user.
Notice a slight difference between `plugins.yml` as part of the Configuration as Code vs `plugins.txt` known from the Jenkins container setups. The latter one will need to contain all plugins and their dependencies and will usually be auto generated to support starting a Jenkins container with all the plug-ins one likes. The `plugin.yml` takes the approach of only mentioning the plugin and their version (or latest) the user really cares about, and Configuration as Code will resolve dependencies for the user.
This means the team above will only have to maintain the `plugins.yml` entries for plugins they use and then make sure their clean Jenkins they start have the Configuration as Code plug-in installed. That can be done with a customized container image or the one supplied with Configuration as Code plugin.
_Migration step-by-step guide:_ For the exact steps, see this part of the migration guide - TBD when all relevant issues fixed:
* [#6 about reloading configuration when changed](https://github.com/jenkinsci/configuration-as-code-plugin/issues/6)
* [#7 about plug-in installation support](https://github.com/jenkinsci/configuration-as-code-plugin/issues/7)
* [#32 where to draft a migration to Jenkins Configuration as Code guide](https://github.com/jenkinsci/configuration-as-code-plugin/issues/32)
* [#65 helping users migrate by export existing configuration](https://github.com/jenkinsci/configuration-as-code-plugin/issues/65)
* [#70 explaining we need the Docker image the team above need to use](https://github.com/jenkinsci/configuration-as-code-plugin/issues/70)
* [#6 about reloading configuration when changed](https://github.com/jenkinsci/configuration-as-code-plugin/issues/6)
* [#7 about plug-in installation support](https://github.com/jenkinsci/configuration-as-code-plugin/issues/7)
* [#32 where to draft a migration to Jenkins Configuration as Code guide](https://github.com/jenkinsci/configuration-as-code-plugin/issues/32)
* [#65 helping users migrate by export existing configuration](https://github.com/jenkinsci/configuration-as-code-plugin/issues/65)
* [#70 explaining we need the Docker image the team above need to use](https://github.com/jenkinsci/configuration-as-code-plugin/issues/70)

View File

@ -82,7 +82,7 @@
1. Execute: `export VAULT_TOKEN="[VAULT_TOKEN]"` where _Vault Token_ is used
1. Execute: `curl --header "X-Vault-Token: $VAULT_TOKEN" --request POST --data '{"bar": "Baz"}' http://vault.domain.local:8200/v1/secret/foo` to put test data into the vault. No output is returned if it works
1. Execute: `curl --header "X-Vault-Token: $VAULT_TOKEN" http://vault.domain.local:8200/v1/secret/foo` to get test data from the vault. Expected output is json formatted:
1. Execute: `curl --header "X-Vault-Token: $VAULT_TOKEN" http://vault.domain.local:8200/v1/secret/foo` to get test data from the vault. Expected output is JSON formatted:
```json
{
@ -97,4 +97,4 @@
"warnings":null,
"auth":null
}
```
```

View File

@ -27,7 +27,7 @@ public class JiraTest {
/* JENKINS-52906
* assertEquals(2, descriptor.getSites().length);
* assertEquals("http://jira.codehaus.org/", sites[0].getUrl().toString());
* assertEquals("http://issues.jenkins-ci.org/", sites[1].getUrl().toString());
* assertEquals("http://issues.jenkins.io/", sites[1].getUrl().toString());
*/
assertEquals(1, descriptor.getSites().length);

View File

@ -2,6 +2,6 @@ unclassified:
jiraProjectProperty:
sites:
url: "http://jira.codehaus.org/"
# see https://issues.jenkins-ci.org/browse/JENKINS-52906
# see https://issues.jenkins.io/browse/JENKINS-52906
# - url: "http://jira.codehaus.org/"
# - url: "http://issues.jenkins-ci.org/"
# - url: "http://issues.jenkins.io/"

View File

@ -15,7 +15,7 @@
<name>Configuration as Code Plugin</name>
<description>Manage Jenkins master configuration as code</description>
<url>https://wiki.jenkins-ci.org/display/JENKINS/Configuration+as+Code+Plugin</url>
<url>https://wiki.jenkins.io/display/JENKINS/Configuration+as+Code+Plugin</url>
<dependencies>
<dependency>
@ -24,7 +24,7 @@
<version>${project.version}</version>
</dependency>
<!--TODO: This should be in a seperate plugin at some point -->
<!--TODO: This should be in a separate plugin at some point -->
<dependency>
<groupId>com.bettercloud</groupId>
<artifactId>vault-java-driver</artifactId>
@ -94,7 +94,7 @@
<excludes combine.children="append">
<!-- Safe, https://github.com/jenkinsci/active-directory-plugin/pull/84 -->
<exclude>org.jvnet.com4j:com4j</exclude>
<!-- Docker Java API Plugin issues, https://issues.jenkins-ci.org/browse/JENKINS-49369 -->
<!-- Docker Java API Plugin issues, https://issues.jenkins.io/browse/JENKINS-49369 -->
<exclude>org.apache.commons:commons-compress</exclude>
</excludes>
</requireUpperBoundDeps>

View File

@ -26,7 +26,7 @@ public class JNLPLauncherConfigurator extends DataBoundConfigurator<JNLPLauncher
try {
return super.instance(config, context);
} catch (ConfiguratorException e) {
// see https://issues.jenkins-ci.org/browse/JENKINS-51603
// see https://issues.jenkins.io/browse/JENKINS-51603
final CNode tunnel = config.get("tunnel");
final CNode vmargs = config.get("vmargs");
return new JNLPLauncher(tunnel != null ? tunnel.asScalar().getValue() : null,

View File

@ -241,7 +241,7 @@ public class PluginManagerConfigurator extends BaseConfigurator<PluginManager> i
* Update sites doesn't give us metadata about hosted plugins, but "latest" version. So here we workaround this by
* searching update site for plugin shortname and we bake specific version's URL based on this URL, assuming this
* will be the same but version part in the path. This is a bit fragile but we don't have a better way so far.
* see <a href="https://issues.jenkins-ci.org/browse/INFRA-1696">INFRA-1696</a> for status
* see <a href="https://issues.jenkins.io/browse/INFRA-1696">INFRA-1696</a> for status
*
* @param updateCenter
* @param p