Skip to content

Commit

Permalink
Merge pull request #65 from virgilbourassa/clean_feature_additions
Browse files Browse the repository at this point in the history
Clean feature additions
  • Loading branch information
qualman authored May 27, 2021
2 parents baa935a + 6d83cfe commit 7f21787
Show file tree
Hide file tree
Showing 6 changed files with 781 additions and 318 deletions.
4 changes: 2 additions & 2 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ PKG_NAME=rundeck

default: build

build: fmtcheck
go install
build: fmt fmtcheck
env go install

test: fmtcheck
go test -i $(TEST) || exit 1
Expand Down
140 changes: 101 additions & 39 deletions rundeck/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"context"
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"strings"

Expand All @@ -44,10 +45,12 @@ type JobSummary struct {
Description string `xml:"description,omitempty"`
}

/*
type jobSummaryList struct {
XMLName xml.Name `xml:"jobs"`
Jobs []JobSummary `xml:"job"`
}
*/

// JobDetail is a comprehensive description of a job, including its entire definition.
type JobDetail struct {
Expand Down Expand Up @@ -75,6 +78,7 @@ type JobDetail struct {
NodesSelectedByDefault *Boolean `xml:"nodesSelectedByDefault"`
Schedule *JobSchedule `xml:"schedule,omitempty"`
ScheduleEnabled bool `xml:"scheduleEnabled"`
TimeZone string `xml:"timeZone,omitempty"`
}

type Boolean struct {
Expand Down Expand Up @@ -108,21 +112,16 @@ type WebHookNotification struct {
type NotificationUrls []string

type JobSchedule struct {
XMLName xml.Name `xml:"schedule"`
DayOfMonth *JobScheduleDayOfMonth `xml:"dayofmonth,omitempty"`
Time JobScheduleTime `xml:"time"`
Month JobScheduleMonth `xml:"month"`
WeekDay *JobScheduleWeekDay `xml:"weekday,omitempty"`
Year JobScheduleYear `xml:"year"`
}

type JobScheduleDayOfMonth struct {
XMLName xml.Name `xml:"dayofmonth"`
XMLName xml.Name `xml:"schedule"`
Time JobScheduleTime `xml:"time"`
Month JobScheduleMonth `xml:"month"`
WeekDay JobScheduleWeekDay `xml:"weekday"`
Year JobScheduleYear `xml:"year"`
}

type JobScheduleMonth struct {
XMLName xml.Name `xml:"month"`
Day string `xml:"day,attr,omitempty"`
Day string `xml:"day,attr"`
Month string `xml:"month,attr"`
}

Expand Down Expand Up @@ -173,6 +172,9 @@ type JobOption struct {
// into job commands.
Name string `xml:"name,attr,omitempty"`

// The displayed label of the option.
Label string `xml:"label,omitempty"`

// Regular expression to be used to validate the option value.
ValidationRegex string `xml:"regex,attr,omitempty"`

Expand Down Expand Up @@ -212,12 +214,15 @@ type JobCommandSequence struct {
XMLName xml.Name `xml:"sequence"`

// If set, Rundeck will continue with subsequent commands after a command fails.
ContinueOnError bool `xml:"keepgoing,attr"`
ContinueOnError bool `xml:"keepgoing,attr,omitempty"`

// Chooses the strategy by which Rundeck will execute commands. Can either be "node-first" or
// "step-first".
OrderingStrategy string `xml:"strategy,attr,omitempty"`

// Log outputs to be captured and used across command sequence
GlobalLogFilters *[]JobLogFilter `xml:"pluginConfig>LogFilter,omitempty"`

// Sequence of commands to run in the sequence.
Commands []JobCommand `xml:"command"`

Expand All @@ -231,12 +236,12 @@ type JobCommandSequence struct {
type JobCommand struct {
XMLName xml.Name

// If the Workflow keepgoing is false, this allows the Workflow to continue when the Error Handler is successful.
ContinueOnError bool `xml:"keepgoingOnSuccess,attr,omitempty"`

// Description
Description string `xml:"description,omitempty"`

// If the Workflow keepgoing is false, this allows the Workflow to continue when the Error Handler is successful.
KeepGoingOnSuccess bool `xml:"keepgoingOnSuccess,attr,omitempty"`

// On error:
ErrorHandler *JobCommand `xml:"errorhandler,omitempty"`

Expand All @@ -256,7 +261,7 @@ type JobCommand struct {
// When ScriptFile is set, the arguments to provide to the script when executing it.
ScriptFileArgs string `xml:"scriptargs,omitempty"`

// ScriptInterpreter is used to execute (Script)File with.
// ScriptInterpreter is used to execute ScriptFile.
ScriptInterpreter *JobCommandScriptInterpreter `xml:"scriptinterpreter,omitempty"`

// A reference to another job to run as this command.
Expand Down Expand Up @@ -303,8 +308,9 @@ type JobPluginConfig map[string]string
// JobNodeFilter describes which nodes from the project's resource list will run the configured
// commands.
type JobNodeFilter struct {
ExcludePrecedence bool `xml:"excludeprecedence"`
Query string `xml:"filter,omitempty"`
ExcludeQuery string `xml:"filterExclude,omitempty"`
ExcludePrecedence bool `xml:"excludeprecedence,omitempty"`
}

type jobImportResults struct {
Expand All @@ -326,13 +332,26 @@ type jobImportResult struct {
Error string `xml:"error"`
}

type JobLogFilter struct {
XMLName xml.Name `xml:"LogFilter"`
Type string `xml:"type,attr"`
Config *JobLogFilterConfig `xml:"config,omitempty"`
}

// JobLogFilterConfig is a specialization of map[string]string for job log filter configuration.
type JobLogFilterConfig map[string]string

type xmlJobLogFilterConfigEntry struct {
XMLName xml.Name
Value string `xml:",chardata"`
}

type JobDispatch struct {
ExcludePrecedence *Boolean `xml:"excludePrecedence"`
MaxThreadCount int `xml:"threadcount,omitempty"`
ContinueOnError bool `xml:"keepgoing"`
RankAttribute string `xml:"rankAttribute,omitempty"`
RankOrder string `xml:"rankOrder,omitempty"`
SuccessOnEmptyNodeFilter bool `xml:"successOnEmptyNodeFilter,omitempty"`
MaxThreadCount int `xml:"threadcount,omitempty"`
ContinueNextNodeOnError bool `xml:"keepgoing,omitempty"`
RankAttribute string `xml:"rankAttribute,omitempty"`
RankOrder string `xml:"rankOrder,omitempty"`
SuccessOnEmptyNodeFilter bool `xml:"successOnEmptyNodeFilter,omitempty"`
}

// GetJobSummariesForProject returns summaries of the jobs belonging to the named project.
Expand Down Expand Up @@ -364,12 +383,17 @@ func GetJob(c *rundeck.BaseClient, id string) (*JobDetail, error) {
return nil, &NotFoundError{}
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Error getting job: (%v)", err)
return nil, fmt.Errorf("error getting job: (%v)", err)
}

respBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}

xml.Unmarshal(respBytes, jobList)
if err := xml.Unmarshal(respBytes, jobList); err != nil {
return nil, err
}

return &jobList.Jobs[0], nil
}
Expand Down Expand Up @@ -444,10 +468,9 @@ func importJob(c *rundeck.BaseClient, job *JobDetail, dupeOption string) (*JobSu

func (c NotificationEmails) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
if len(c) > 0 {
return xml.Attr{name, strings.Join(c, ",")}, nil
} else {
return xml.Attr{}, nil
return xml.Attr{Name: name, Value: strings.Join(c, ",")}, nil
}
return xml.Attr{}, nil
}

func (c *NotificationEmails) UnmarshalXMLAttr(attr xml.Attr) error {
Expand All @@ -458,10 +481,9 @@ func (c *NotificationEmails) UnmarshalXMLAttr(attr xml.Attr) error {

func (c NotificationUrls) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
if len(c) > 0 {
return xml.Attr{name, strings.Join(c, ",")}, nil
} else {
return xml.Attr{}, nil
return xml.Attr{Name: name, Value: strings.Join(c, ",")}, nil
}
return xml.Attr{}, nil
}

func (c *NotificationUrls) UnmarshalXMLAttr(attr xml.Attr) error {
Expand All @@ -472,10 +494,9 @@ func (c *NotificationUrls) UnmarshalXMLAttr(attr xml.Attr) error {

func (c JobValueChoices) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
if len(c) > 0 {
return xml.Attr{name, strings.Join(c, ",")}, nil
} else {
return xml.Attr{}, nil
return xml.Attr{Name: name, Value: strings.Join(c, ",")}, nil
}
return xml.Attr{}, nil
}

func (c *JobValueChoices) UnmarshalXMLAttr(attr xml.Attr) error {
Expand All @@ -486,19 +507,25 @@ func (c *JobValueChoices) UnmarshalXMLAttr(attr xml.Attr) error {

func (a JobCommandJobRefArguments) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Attr = []xml.Attr{
xml.Attr{xml.Name{Local: "line"}, string(a)},
{Name: xml.Name{Local: "line"}, Value: string(a)},
}
e.EncodeToken(start)
e.EncodeToken(xml.EndElement{start.Name})
return nil
err := e.EncodeToken(start)
if err != nil {
return err
}
err = e.EncodeToken(xml.EndElement{Name: start.Name})
return err
}

func (a *JobCommandJobRefArguments) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type jobRefArgs struct {
Line string `xml:"line,attr"`
}
args := jobRefArgs{}
d.DecodeElement(&args, &start)
err := d.DecodeElement(&args, &start)
if err != nil {
return err
}

*a = JobCommandJobRefArguments(args.Line)

Expand All @@ -515,6 +542,41 @@ func (c *JobPluginConfig) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e
return unmarshalMapFromXML(rc, d, start, "entry", "key", "value")
}

// Global log filter plugin configurations are marshalled differently than other plugins
func (config JobLogFilterConfig) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if len(config) == 0 {
return nil
}

if err := e.EncodeToken(start); err != nil {
return err
}

for key, value := range config {
configEntry := xmlJobLogFilterConfigEntry{XMLName: xml.Name{Local: key}, Value: value}
if err := e.Encode(configEntry); err != nil {
return err
}
}
return e.EncodeToken(start.End())
}

// Global log filter plugin configurations are unmarshalled differently than other plugins
func (config *JobLogFilterConfig) UnmarshalXML(d *xml.Decoder, _ xml.StartElement) error {
*config = JobLogFilterConfig{}
for {
var entry xmlJobLogFilterConfigEntry

if err := d.Decode(&entry); err == io.EOF {
break
} else if err != nil {
return err
}
(*config)[entry.XMLName.Local] = entry.Value
}
return nil
}

// JobSummary produces a JobSummary instance with values populated from the import result.
// The summary object won't have its Description populated, since import results do not
// include descriptions.
Expand Down
Loading

0 comments on commit 7f21787

Please sign in to comment.