Skip to content

Commit

Permalink
add job declarative actions to provider
Browse files Browse the repository at this point in the history
  • Loading branch information
jgramoll committed Jul 31, 2019
1 parent 995ac14 commit 5b54ec1
Show file tree
Hide file tree
Showing 20 changed files with 564 additions and 42 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ resource "jenkins_job" "premerge" {
name = "Premerge checks"
}
resource "jenkins_job_declarative_job_action" premerge {
job = "${jenkins_job.premerge.id}"
}
resource "jenkins_job_declarative_job_property_tracker_action" premerge {
job = "${jenkins_job.premerge.id}"
}
resource "jenkins_job_git_scm" "premerge" {
job = "${jenkins_job.premerge.id}"
Expand Down
39 changes: 37 additions & 2 deletions client/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import (
// ErrJobPropertyNotFound job property not found
var ErrJobPropertyNotFound = errors.New("Could not find job property")

// ErrJobActionNotFound job action not found
var ErrJobActionNotFound = errors.New("Could not find job action")

// Job
type Job struct {
Id string
Name string
Disabled bool
Actions *JobConfigActions `xml:"actions"`
Actions *JobActions `xml:"actions"`
Description string
KeepDependencies bool
Properties *JobProperties
Expand All @@ -23,7 +26,7 @@ type Job struct {
// NewJob return Job object with default values
func NewJob() *Job {
return &Job{
Actions: NewJobConfigActions(),
Actions: NewJobActions(),
KeepDependencies: false,
Properties: NewJobProperties(),
}
Expand Down Expand Up @@ -80,3 +83,35 @@ func (job *Job) DeleteProperty(propertyId string) error {
}
return ErrJobPropertyNotFound
}

func (job *Job) GetAction(actionId string) (JobAction, error) {
for _, action := range *job.Actions.Items {
if action.GetId() == actionId {
return action, nil
}
}
return nil, ErrJobActionNotFound
}

func (job *Job) UpdateAction(action JobAction) error {
actions := *job.Actions.Items
actionId := action.GetId()
for i, oldAction := range actions {
if oldAction.GetId() == actionId {
actions[i] = action
return nil
}
}
return ErrJobActionNotFound
}

func (job *Job) DeleteAction(actionId string) error {
actions := *job.Actions.Items
for i, action := range actions {
if action.GetId() == actionId {
*job.Actions.Items = append(actions[:i], actions[i+1:]...)
return nil
}
}
return ErrJobActionNotFound
}
5 changes: 5 additions & 0 deletions client/job_action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package client

type JobAction interface {
GetId() string
}
26 changes: 13 additions & 13 deletions client/job_config_actions.go → client/job_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,44 @@ import (
"encoding/xml"
)

type JobConfigActions struct {
XMLName xml.Name `xml:"actions"`
Items *[]JobConfigAction `xml:",any"`
type JobActions struct {
XMLName xml.Name `xml:"actions"`
Items *[]JobAction `xml:",any"`
}

func NewJobConfigActions() *JobConfigActions {
return &JobConfigActions{
Items: &[]JobConfigAction{},
func NewJobActions() *JobActions {
return &JobActions{
Items: &[]JobAction{},
}
}

func (actions *JobConfigActions) Append(action JobConfigAction) *JobConfigActions {
newActions := NewJobConfigActions()
func (actions *JobActions) Append(action JobAction) *JobActions {
newActions := NewJobActions()
if actions.Items != nil {
*newActions.Items = append(*actions.Items, action)
} else {
*newActions.Items = []JobConfigAction{action}
*newActions.Items = []JobAction{action}
}
return newActions
}

func (actions *JobConfigActions) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
func (actions *JobActions) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var tok xml.Token
var err error
actions.Items = &[]JobConfigAction{}
actions.Items = &[]JobAction{}
for tok, err = d.Token(); err == nil; tok, err = d.Token() {
if elem, ok := tok.(xml.StartElement); ok {
// TODO use map
switch elem.Name.Local {
case "org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobAction":
action := NewJobConfigDeclarativeJobAction()
action := NewJobDeclarativeJobAction()
err := d.DecodeElement(action, &elem)
if err != nil {
return err
}
*actions.Items = append(*actions.Items, action)
case "org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction":
action := NewJobConfigDeclarativeJobPropertyTrackerAction()
action := NewJobDeclarativeJobPropertyTrackerAction()
err := d.DecodeElement(action, &elem)
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion client/job_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type jobConfig struct {
Id string `xml:"id,attr,omitempty"`
Plugin string `xml:"plugin,attr,omitempty"`

Actions *JobConfigActions `xml:"actions"`
Actions *JobActions `xml:"actions"`
Description string `xml:"description"`
KeepDependencies bool `xml:"keepDependencies"`
Properties *JobProperties `xml:"properties"`
Expand Down
3 changes: 0 additions & 3 deletions client/job_config_action.go

This file was deleted.

16 changes: 0 additions & 16 deletions client/job_config_declarative_job_action.go

This file was deleted.

4 changes: 2 additions & 2 deletions client/job_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
func TestJobConfigSerialize(t *testing.T) {
job := NewJob()
job.Description = "my-desc"
job.Actions = job.Actions.Append(NewJobConfigDeclarativeJobAction())
job.Actions = job.Actions.Append(NewJobConfigDeclarativeJobPropertyTrackerAction())
job.Actions = job.Actions.Append(NewJobDeclarativeJobAction())
job.Actions = job.Actions.Append(NewJobDeclarativeJobPropertyTrackerAction())

definition := NewCpsScmFlowDefinition()
definition.SCM = NewGitScm()
Expand Down
16 changes: 16 additions & 0 deletions client/job_declarative_job_action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package client

import "encoding/xml"

type JobDeclarativeJobAction struct {
XMLName xml.Name `xml:"org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobAction"`
Id string `xml:"id,attr,omitempty"`
}

func NewJobDeclarativeJobAction() *JobDeclarativeJobAction {
return &JobDeclarativeJobAction{}
}

func (action *JobDeclarativeJobAction) GetId() string {
return action.Id
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package client

import "encoding/xml"

type JobConfigDeclarativeJobPropertyTrackerAction struct {
type JobDeclarativeJobPropertyTrackerAction struct {
XMLName xml.Name `xml:"org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction"`
Id string `xml:"id,attr,omitempty"`

Expand All @@ -12,10 +12,10 @@ type JobConfigDeclarativeJobPropertyTrackerAction struct {
Options string `xml:"options"`
}

func NewJobConfigDeclarativeJobPropertyTrackerAction() *JobConfigDeclarativeJobPropertyTrackerAction {
return &JobConfigDeclarativeJobPropertyTrackerAction{}
func NewJobDeclarativeJobPropertyTrackerAction() *JobDeclarativeJobPropertyTrackerAction {
return &JobDeclarativeJobPropertyTrackerAction{}
}

func (action *JobConfigDeclarativeJobPropertyTrackerAction) GetId() string {
func (action *JobDeclarativeJobPropertyTrackerAction) GetId() string {
return action.Id
}
12 changes: 12 additions & 0 deletions provider/job_action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package provider

import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/jgramoll/terraform-provider-jenkins/client"
)

type jobAction interface {
fromClientAction(client.JobAction) (jobAction, error)
toClientAction(id string) (client.JobAction, error)
setResourceData(*schema.ResourceData) error
}
163 changes: 163 additions & 0 deletions provider/job_action_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package provider

import (
"errors"
"log"
"strings"

"github.com/google/uuid"
"github.com/hashicorp/terraform/helper/schema"
"github.com/mitchellh/mapstructure"
)

// ErrInvalidJobActionId
var ErrInvalidJobActionId = errors.New("Invalid action id, must be jobName\xactionId")

func resourceJobActionId(input string) (jobName string, actionId string, err error) {
parts := strings.Split(input, IdDelimiter)
if len(parts) != 2 {
err = ErrInvalidJobActionId
return
}
jobName = parts[0]
actionId = parts[1]
return
}

func resourceJobActionCreate(d *schema.ResourceData, m interface{}, createJobAction func() jobAction) error {
jobName := d.Get("job").(string)

action := createJobAction()
configRaw := d.Get("").(map[string]interface{})
if err := mapstructure.Decode(configRaw, &action); err != nil {
return err
}

id, err := uuid.NewRandom()
if err != nil {
return err
}
actionId := id.String()

jobService := m.(*Services).JobService
jobLock.Lock(jobName)
j, err := jobService.GetJob(jobName)
if err != nil {
jobLock.Unlock(jobName)
return err
}

clientAction, err := action.toClientAction(actionId)
if err != nil {
jobLock.Unlock(jobName)
return err
}
j.Actions = j.Actions.Append(clientAction)
err = jobService.UpdateJob(j)
jobLock.Unlock(jobName)
if err != nil {
return err
}

d.SetId(strings.Join([]string{jobName, actionId}, IdDelimiter))
log.Println("[DEBUG] Creating job action:", d.Id())
return resourceJobActionRead(d, m, createJobAction)
}

func resourceJobActionRead(d *schema.ResourceData, m interface{}, createJobAction func() jobAction) error {
jobName, actionId, err := resourceJobActionId(d.Id())
if err != nil {
return err
}

jobService := m.(*Services).JobService
jobLock.RLock(jobName)
j, err := jobService.GetJob(jobName)
jobLock.RUnlock(jobName)
if err != nil {
log.Println("[WARN] No Job found:", err)
d.SetId("")
return nil
}
clientAction, err := j.GetAction(actionId)
if err != nil {
return err
}
action, err := createJobAction().fromClientAction(clientAction)
if err != nil {
return err
}

log.Println("[INFO] Updating state for job action", d.Id())
return action.setResourceData(d)
}

func resourceJobActionUpdate(d *schema.ResourceData, m interface{}, createJobAction func() jobAction) error {
jobName, actionId, err := resourceJobActionId(d.Id())
if err != nil {
return err
}

action := createJobAction()
configRaw := d.Get("").(map[string]interface{})
if err := mapstructure.Decode(configRaw, &action); err != nil {
return err
}

jobService := m.(*Services).JobService
jobLock.Lock(jobName)
j, err := jobService.GetJob(jobName)
if err != nil {
jobLock.Unlock(jobName)
return err
}

clientAction, err := action.toClientAction(actionId)
if err != nil {
jobLock.Unlock(jobName)
return err
}
err = j.UpdateAction(clientAction)
if err != nil {
jobLock.Unlock(jobName)
return err
}
err = jobService.UpdateJob(j)
jobLock.Unlock(jobName)
if err != nil {
return err
}

log.Println("[DEBUG] Updating job action", d.Id())
return resourceJobActionRead(d, m, createJobAction)
}

func resourceJobActionDelete(d *schema.ResourceData, m interface{}, createJobAction func() jobAction) error {
jobName, actionId, err := resourceJobActionId(d.Id())
if err != nil {
return err
}

jobService := m.(*Services).JobService
jobLock.Lock(jobName)
j, err := jobService.GetJob(jobName)
if err != nil {
jobLock.Unlock(jobName)
return err
}

err = j.DeleteAction(actionId)
if err != nil {
jobLock.Unlock(jobName)
return err
}

err = jobService.UpdateJob(j)
jobLock.Unlock(jobName)
if err != nil {
return err
}

d.SetId("")
return nil
}
Loading

0 comments on commit 5b54ec1

Please sign in to comment.