Skip to content

Commit

Permalink
add git scm
Browse files Browse the repository at this point in the history
  • Loading branch information
jgramoll committed Jul 16, 2019
1 parent de24d38 commit a5d34f1
Show file tree
Hide file tree
Showing 52 changed files with 2,029 additions and 96 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dist/
vendor/
.envrc
terraform-provider-jenkins
91 changes: 90 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,96 @@ provider "jenkins" {
}
resource "jenkins_job" "premerge" {
name = "Premerge checks"
name = "Premerge checks"
}
resource "jenkins_job_git_scm" "premerge" {
job = "${jenkins_job.premerge.id}"
config_version = "2"
script_path = "Jenkinsfile.api"
lightweight = false
}
resource "jenkins_job_git_scm_user_remote_config" "premerge" {
scm = "${jenkins_job_git_scm.premerge.id}"
refspec = "${GERRIT_REFSPEC}"
url = "ssh://git.server/git-repo.git"
credentials_id = "123-abc"
}
resource "jenkins_job_git_scm_branch" "premerge" {
job = "${jenkins_job.premerge.id}"
name = "FETCH_HEAD"
}
resource "jenkins_job_git_scm_clean_before_checkout_extention" "premerge" {
job = "${jenkins_job.premerge.id}"
}
resource "jenkins_job_build_discard_property" "main" {
job = "${jenkins_job.premerge.id}"
strategy = "hudson.tasks.LogRotator"
days_to_keep = "30"
num_to_keep = "-1"
artifact_days_to_keep = "-1"
artifact_num_to_keep = "-1"
}
resource "jenkins_job_pipeline_triggers_property" "main" {
job = "${jenkins_job.premerge.id}"
}
resource "jenkins_job_gerrit_trigger" "main" {
property = "${jenkins_job_pipeline_triggers_property.main.id}"
server_name = "__ANY__"
silent_mode = false
silent_start_mode = false
escape_quotes = true
name_and_email_parameter_mode = "PLAIN"
commit_message_parameter_mode = "BASE64"
change_subject_parameter_mode = "PLAIN"
comment_text_parameter_mode = "BASE64"
skip_vote = {
on_successful = false
on_failed = false
on_unstable = false
on_not_built = false
}
}
resource "jenkins_job_gerrit_trigger_patchset_created_event" "main" {
trigger = "${jenkins_job_gerrit_trigger.main.id}"
exclude_drafts = false
exclude_trivial_rebase = false
exclude_no_code_change = false
exclude_private_state = false
exclude_wip_state = false
}
resource "jenkins_job_gerrit_trigger_draft_published_event" "main" {
trigger = "${jenkins_job_gerrit_trigger.main.id}"
}
resource "jenkins_job_gerrit_project" "main" {
trigger = "${jenkins_job_gerrit_trigger.main.id}"
compareType = "PLAIN"
pattern = "bridge-skills"
}
resource "jenkins_job_gerrit_branch" "main" {
project = "${jenkins_job_gerrit_project.main.id}"
compareType = "REG_EXP"
pattern = "^(?!refs/meta/config).*$"
}
```
8 changes: 5 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ func (client *Client) NewRequestWithBody(method string, path string, data interf
return nil, xmlErr
}

log.Printf("[INFO] Sending %s %s with body %s\n", method, reqURL, xmlValue)
req, err := http.NewRequest(method, reqURL.String(), bytes.NewBuffer(xmlValue))
body := bytes.NewBuffer(xmlValue)
log.Printf("[INFO] Sending %s %s with body %s\n", method, reqURL, body)
req, err := http.NewRequest(method, reqURL.String(), body)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -132,7 +133,8 @@ func validateResponse(r *http.Response) error {

jenkinsError := JenkinsError{}
err := xml.Unmarshal([]byte(bodyString), &jenkinsError)
if err != nil {
// Hack around malformed html
if err != nil && err.Error() != "XML syntax error on line 10: element <hr> closed by </body>" {
return err
}

Expand Down
22 changes: 22 additions & 0 deletions client/cps_scm_flow_definition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package client

type CpsScmFlowDefinition struct {
Class string `xml:"class,attr"`

Id string `xml:"id,attr"`
SCM *GitSCM `xml:"scm"`
ScriptPath string `xml:"scriptPath"`
Lightweight bool `xml:"lightweight"`
}

func NewCpsScmFlowDefinition() *CpsScmFlowDefinition {
return &CpsScmFlowDefinition{
Class: "org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition",
}
}

// func (definition *CpsScmFlowDefinition) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
// start.Name.Local = "asdf"
// e.
// return nil
// }
22 changes: 22 additions & 0 deletions client/cps_scm_flow_definition_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package client

import (
"encoding/xml"
"testing"
)

func TestCpsScmFlowDefinitionSerialize(t *testing.T) {
definition := NewCpsScmFlowDefinition()
resultBytes, err := xml.MarshalIndent(definition, "", "\t")
if err != nil {
t.Fatalf("failed to serialize xml %s", err)
}
result := string(resultBytes)
expected := `<CpsScmFlowDefinition class="org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition" id="">
<scriptPath></scriptPath>
<lightweight>false</lightweight>
</CpsScmFlowDefinition>`
if result != expected {
t.Fatalf("job definition should be %s, was %s", expected, result)
}
}
29 changes: 29 additions & 0 deletions client/git_user_remote_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package client

type GitUserRemoteConfigs struct {
Items *[]*GitUserRemoteConfig `xml:"hudson.plugins.git.UserRemoteConfig"`
}

func NewGitUserRemoteConfigs() *GitUserRemoteConfigs {
return &GitUserRemoteConfigs{
Items: &[]*GitUserRemoteConfig{},
}
}

func (configs *GitUserRemoteConfigs) Append(config *GitUserRemoteConfig) *GitUserRemoteConfigs {
var newConfigItems []*GitUserRemoteConfig
if (configs.Items != nil) {
newConfigItems = append(*configs.Items, config)
} else {
newConfigItems = append(newConfigItems, config)
}
newConfigs := NewGitUserRemoteConfigs()
newConfigs.Items = &newConfigItems
return newConfigs
}

type GitUserRemoteConfig struct {
Refspec string `xml:"refspec"`
Url string `xml:"url"`
CredentialsId string `xml:"credentialsId"`
}
43 changes: 35 additions & 8 deletions client/jenkins_error.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,48 @@
package client

import (
"encoding/xml"
"fmt"
)

// JenkinsError Error response from jenkins
type JenkinsError struct {
ErrorMsg string `xml:"error"`
Exception string `xml:"exception"`
Message string `xml:"message"`
Status int `xml:"status"`
Timestamp int64 `xml:"timestamp"`
Body string `xml:"body"`
XMLName xml.Name `xml:"html"`
Title string
Message string
}

// For error interface
func (r *JenkinsError) Error() string {
return fmt.Sprintf("%d %v: %v%v\n%v", r.Status, r.ErrorMsg, r.Message,
r.Body, r.Exception)
return fmt.Sprintf("%v: %v", r.Title, r.Message)
}

func (jenkinsError *JenkinsError) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var tok xml.Token
var err error
for tok, err = d.Token(); err == nil; tok, err = d.Token() {
if elem, ok := tok.(xml.StartElement); ok {
switch elem.Name.Local {
case "title":
tok, err = d.Token()
if err != nil {
return err
}
if char, ok := tok.(xml.CharData); ok {
jenkinsError.Title = string(char)
}
case "p":
fallthrough
case "pre":
tok, err = d.Token()
if err != nil {
return err
}
if char, ok := tok.(xml.CharData); ok {
jenkinsError.Message += string(char)
}
}
}
}
return err
}
38 changes: 37 additions & 1 deletion client/job.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package client

import (
"errors"
"strings"
)

// ErrJobPropertyNotFound job property not found
var ErrJobPropertyNotFound = errors.New("Could not find job property")

// Job
type Job struct {
Id string
Name string
Disabled bool
Description string
Properties *JobProperties
Definition JobDefinition
}

// NewJob return Job object with default values
func NewJob() *Job {
return &Job{}
return &Job{
Properties: NewJobProperties(),
}
}

func (job *Job) Folder() string {
Expand All @@ -35,8 +44,35 @@ func newJobFromConfigAndDetails(config *jobConfig, details *jobDetails) *Job {
}

if config != nil {
job.Id = config.Id
job.Disabled = config.Disabled
job.Properties = config.Properties
if config.Definition != nil {
job.Definition = config.Definition.Item
}
}

return &job
}

func (job *Job) GetProperty(propertyId string) (JobProperty, error) {
properties := *(*job.Properties).Items
for _, property := range properties {
if property.GetId() == propertyId {
return property, nil
}
}
return nil, ErrJobPropertyNotFound
}

func (job *Job) DeleteProperty(propertyId string) error {
properties := *(*job.Properties).Items
for i, property := range properties {
if property.GetId() == propertyId {
properties = append(properties[:i], properties[i+1:]...)
job.Properties.Items = &properties
return nil
}
}
return ErrJobPropertyNotFound
}
25 changes: 19 additions & 6 deletions client/job_config.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
package client

import "encoding/xml"
import (
"encoding/xml"
)

type jobConfig struct {
XMLName xml.Name `xml:"flow-definition"`
Id string `xml:"id,attr"`
Plugin string `xml:"plugin,attr"`

// actions
Description string `xml:"description"`
// keepDependencies
// properties
Definition *JobDefinition `xml:"definition"`
Triggers *[]*Trigger `xml:"triggers"`
Disabled bool `xml:"disabled"`
Properties *JobProperties `xml:"properties"`
Definition *JobDefinitionXml `xml:"definition"`
// Triggers *[]*Trigger `xml:"triggers"`
Disabled bool `xml:"disabled"`
}

func JobConfigFromJob(job *Job) *jobConfig {
return &jobConfig{}
return &jobConfig{
Id: job.Id,
Description: job.Description,
Disabled: job.Disabled,
Properties: job.Properties,
Definition: &JobDefinitionXml{
Item: job.Definition,
},
}
}
24 changes: 24 additions & 0 deletions client/job_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package client

import (
"encoding/xml"
"testing"
)

func TestJobConfigSerialize(t *testing.T) {
job := NewJob()
config := JobConfigFromJob(job)
resultBytes, err := xml.MarshalIndent(config, "", "\t")
if err != nil {
t.Fatalf("failed to serialize xml %s", err)
}
result := string(resultBytes)
expected := `<flow-definition id="" plugin="workflow-job@2.33">
<description></description>
<properties></properties>
<disabled>false</disabled>
</flow-definition>`
if result != expected {
t.Fatalf("job definition should be %s, was %s", expected, result)
}
}
Loading

0 comments on commit a5d34f1

Please sign in to comment.