Skip to content

Commit

Permalink
First Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ltamaster committed Sep 5, 2018
0 parents commit bb8aacb
Show file tree
Hide file tree
Showing 14 changed files with 1,101 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.gradle
.idea
build
gradle
96 changes: 96 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Git Plugin

This is a git plugin (based on [Jgit](https://www.eclipse.org/jgit/)) which contain a Resource model and worflow steps

For authentication, it can be used a private key or a password.
If the private key is not defined, then the password will be used.

* The primary key will work with SSH protocol on the Git URL.
* The password will work with http/https protocol on the Git URL (the most of the case, the username is needed on the URI, eg: `http[s]://username@host.xz[:port]/path/to/repo.git/` when you use password authentication)


## Build

Run the following command to built the jar file:

```
./gradlew clean build
```

## Install

Copy the `git-plugin-x.y.x.jar` file to the `$RDECK_BASE/libext/` directory inside your Rundeck installation.


## GIT Resource Model

This is a resource model plugin that uses Git to store resources model file.

### Configuration

You need to set up the following options to use the plugin:

![](images/resource_model.png)

### Repo Settings

* **Base Directory**: Directory for checkout
* **Git URL**: Checkout URL.
See [git-clone](https://www.kernel.org/pub/software/scm/git/docs/git-clone.html)
specifically the [GIT URLS](https://www.kernel.org/pub/software/scm/git/docs/git-clone.html#URLS) section.
Some examples:
* `ssh://[user@]host.xz[:port]/path/to/repo.git/`
* `git://host.xz[:port]/path/to/repo.git/`
* `http[s]://host.xz[:port]/path/to/repo.git/`
* `ftp[s]://host.xz[:port]/path/to/repo.git/`
* `rsync://host.xz/path/to/repo.git/`

* **Branch**: Checkout branch
* **Resource model File**: Resource model file inside the github repo. This is the file that will be added to Rundeck resource model.
* **File Format**: File format of the resource model, it could be xml, yaml, json
* **Writable**: Allow to write the remote file

### Authentication

* **Git Password**: Password to authenticate remotely
* **SSH: Strict Host Key Checking**: Use strict host key checking.
If `yes`, require remote host SSH key is defined in the `~/.ssh/known_hosts` file, otherwise do not verify.
* **SSH Key Path**: SSH Key Path to authenticate

### Limitations

* The plugin needs to clone the full repo on the local directory path (Base Directory option) to get the file that will be added to the resource model.
* Any time that you edit the nodes on the GUI, the commit will be perfomed with the message `Edit node from GUI` (it is not editable)

## GIT Clone Workflow Step

This plugin clone a git repo into a rundeck server folder

### Configuration

You need to set up the following options to use the plugin:

![](images/clone-workflow-step.png)

### Repo Settings

* **Base Directory**: Directory for checkout
* **Git URL**: Checkout URL.
See [git-clone](https://www.kernel.org/pub/software/scm/git/docs/git-clone.html)
specifically the [GIT URLS](https://www.kernel.org/pub/software/scm/git/docs/git-clone.html#URLS) section.
Some examples:
* `ssh://[user@]host.xz[:port]/path/to/repo.git/`
* `git://host.xz[:port]/path/to/repo.git/`
* `http[s]://host.xz[:port]/path/to/repo.git/`
* `ftp[s]://host.xz[:port]/path/to/repo.git/`
* `rsync://host.xz/path/to/repo.git/`

* **Branch**: Checkout branch

### Authentication

* **Password Storage Path**: Password storage path to authenticate remotely
* **SSH: Strict Host Key Checking**: Use strict host key checking.
If `yes`, require remote host SSH key is defined in the `~/.ssh/known_hosts` file, otherwise do not verify.
* **SSH Key Storage Path**: SSH Key storage path to authenticate

80 changes: 80 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
plugins {
id 'pl.allegro.tech.build.axion-release' version '1.3.2'
}

group 'com.rundeck'

ext.rundeckPluginVersion = '1.2'
ext.pluginClassNames='com.rundeck.plugin.GitResourceModelFactory,com.rundeck.plugin.GitCloneWorkflowStep'
ext.pluginName = 'Git Plugin'
ext.pluginDescription = 'Git Plugin'

scmVersion {
tag {
prefix = ''
versionSeparator = ''
def origDeserialize=deserialize
//apend .0 to satisfy semver if the tag version is only X.Y
deserialize = { config, position, tagName ->
def orig = origDeserialize(config, position, tagName)
if (orig.split('\\.').length < 3) {
orig += ".0"
}
orig
}
}
}
project.version = scmVersion.version

apply plugin: 'groovy'
apply plugin: 'java'

repositories {
mavenCentral()
}

configurations {
pluginLibs

compile {
extendsFrom pluginLibs
}
}


dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
testCompile group: 'junit', name: 'junit', version: '4.12'

compile group: 'org.rundeck', name: 'rundeck-core', version: '2.11.4'

pluginLibs( 'org.eclipse.jgit:org.eclipse.jgit:3.7.1.201504261725-r') {
exclude module: 'slf4j-api'
exclude module: 'jsch'
exclude module: 'commons-logging'
}

testCompile "org.codehaus.groovy:groovy-all:2.3.7"
testCompile "org.spockframework:spock-core:0.7-groovy-2.0"
testCompile "cglib:cglib-nodep:2.2.2"
testCompile 'org.objenesis:objenesis:1.4'
}


task copyToLib(type: Copy) {
into "$buildDir/output/lib"
from configurations.pluginLibs
}

jar {
from "$buildDir/output"
manifest {
def libList = configurations.pluginLibs.collect{'lib/' + it.name}.join(' ')
attributes 'Rundeck-Plugin-Classnames': pluginClassNames
attributes 'Rundeck-Plugin-File-Version': project.version
attributes 'Rundeck-Plugin-Version': rundeckPluginVersion
attributes 'Rundeck-Plugin-Archive': 'true'
attributes 'Rundeck-Plugin-Libs': "${libList}"
}
dependsOn(copyToLib)
}
Binary file added images/clone-workflow-step.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/resource_model.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
125 changes: 125 additions & 0 deletions src/main/groovy/com/rundeck/plugin/GitCloneWorkflowStep.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.rundeck.plugin

import com.dtolabs.rundeck.core.execution.workflow.steps.StepException
import com.dtolabs.rundeck.core.plugins.Plugin
import com.dtolabs.rundeck.core.plugins.configuration.Describable
import com.dtolabs.rundeck.core.plugins.configuration.Description
import com.dtolabs.rundeck.core.plugins.configuration.PropertyUtil
import com.dtolabs.rundeck.plugins.PluginLogger
import com.dtolabs.rundeck.plugins.ServiceNameConstants
import com.dtolabs.rundeck.plugins.descriptions.PluginDescription
import com.dtolabs.rundeck.plugins.step.PluginStepContext
import com.dtolabs.rundeck.plugins.step.StepPlugin
import com.dtolabs.rundeck.plugins.util.DescriptionBuilder
import com.rundeck.plugin.util.GitPluginUtil
import groovy.json.JsonOutput


@Plugin(name = GitCloneWorkflowStep.PROVIDER_NAME, service = ServiceNameConstants.WorkflowStep)
@PluginDescription(title = GitCloneWorkflowStep.PROVIDER_TITLE, description = GitCloneWorkflowStep.PROVIDER_DESCRIPTION)
class GitCloneWorkflowStep implements StepPlugin, Describable{
public static final String PROVIDER_NAME = "git-clone-step";
public static final String PROVIDER_TITLE = "Git / Clone"
public static final String PROVIDER_DESCRIPTION ="Clone a Git repository on Rundeck server"

public final static String GIT_URL="gitUrl"
public final static String GIT_BASE_DIRECTORY="gitBaseDirectory"
public final static String GIT_BRANCH="gitBranch"
public final static String GIT_HOSTKEY_CHECKING="strictHostKeyChecking"
public final static String GIT_KEY_STORAGE="gitKeyPath"
public final static String GIT_PASSWORD_STORAGE="gitPasswordPath"


final static Map<String, Object> renderingOptionsAuthentication = GitPluginUtil.getRenderOpt("Authentication", false)
final static Map<String, Object> renderingOptionsAuthenticationPassword = GitPluginUtil.getRenderOpt("Authentication",false, false, true)
final static Map<String, Object> renderingOptionsAuthenticationKey = GitPluginUtil.getRenderOpt("Authentication",false, false, false, true)

final static Map<String, Object> renderingOptionsConfig = GitPluginUtil.getRenderOpt("Configuration",false)

GitManager gitManager

static Description DESCRIPTION = DescriptionBuilder.builder()
.name(PROVIDER_NAME)
.title(PROVIDER_TITLE)
.description(PROVIDER_DESCRIPTION)
.property(
PropertyUtil.string(GIT_BASE_DIRECTORY, "Base Directory", "Directory for checkout.", true,
null, null, null, renderingOptionsConfig))
.property(PropertyUtil.string(GIT_URL, "Git URL", '''Checkout url.
See [git-clone](https://www.kernel.org/pub/software/scm/git/docs/git-clone.html)
specifically the [GIT URLS](https://www.kernel.org/pub/software/scm/git/docs/git-clone.html#URLS) section.
Some examples:
* `ssh://[user@]host.xz[:port]/path/to/repo.git/`
* `git://host.xz[:port]/path/to/repo.git/`
* `http[s]://host.xz[:port]/path/to/repo.git/`
* `ftp[s]://host.xz[:port]/path/to/repo.git/`
* `rsync://host.xz/path/to/repo.git/`''', true,
null,null,null, renderingOptionsConfig))
.property(PropertyUtil.string(GIT_BRANCH, "Branch", "Checkout branch.", true,
"master",null,null, renderingOptionsConfig))
.property(PropertyUtil.string(GIT_PASSWORD_STORAGE, "Git Password", 'Password to authenticate remotely', false,
null,null,null, renderingOptionsAuthenticationPassword))
.property(PropertyUtil.select(GIT_HOSTKEY_CHECKING, "SSH: Strict Host Key Checking", '''Use strict host key checking.
If `yes`, require remote host SSH key is defined in the `~/.ssh/known_hosts` file, otherwise do not verify.''', false,
"yes",GitResourceModelFactory.LIST_HOSTKEY_CHECKING,null, renderingOptionsAuthentication))
.property(PropertyUtil.string(GIT_KEY_STORAGE, "SSH Key Path", 'SSH Key Path', false,
null,null,null, renderingOptionsAuthenticationKey))
.build()

GitCloneWorkflowStep() {
}

@Override
Description getDescription() {
return DESCRIPTION
}

@Override
void executeStep(final PluginStepContext context, final Map<String, Object> configuration) throws StepException {
Properties proConfiguration = new Properties()
proConfiguration.putAll(configuration)

if(gitManager==null){
gitManager = new GitManager(proConfiguration)
}

def localPath=configuration.get(GIT_BASE_DIRECTORY)

if(configuration.get(GIT_PASSWORD_STORAGE)){
def password = GitPluginUtil.getFromKeyStorage(configuration.get(GIT_PASSWORD_STORAGE), context)
gitManager.setGitPassword(password)
}

if(configuration.get(GIT_KEY_STORAGE)){
def key = GitPluginUtil.getFromKeyStorage(configuration.get(GIT_KEY_STORAGE), context)
gitManager.setSshPrivateKey(key)
}

PluginLogger logger = context.getLogger()
logger.log(3, "Cloning Repo ${gitManager.gitURL} to local path ${localPath}")

File base = new File(localPath)

if(!base){
base.mkdir()
}

try{
gitManager.cloneOrCreate(base)

def jsonMap = base.listFiles().collect {file ->
return [name: file.name, directory: file.directory, file: file.file, path: file.absolutePath]
}
def json = JsonOutput.toJson(jsonMap)
logger.log(2, json)

}catch(Exception e){
logger.log(0, e.getMessage())
throw new StepException("Error ${op} VM.", GitFailureReason.AuthenticationError)

}



}
}
12 changes: 12 additions & 0 deletions src/main/groovy/com/rundeck/plugin/GitFailureReason.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.rundeck.plugin

import com.dtolabs.rundeck.core.execution.workflow.steps.FailureReason

enum GitFailureReason implements FailureReason {

/**
* Authentication Error
*/
AuthenticationError,

}
Loading

0 comments on commit bb8aacb

Please sign in to comment.