Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orchestrator Options #107

Merged
merged 7 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added props/tokens.properties
Empty file.
26 changes: 19 additions & 7 deletions rundeck/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ type JobDetail struct {
Timeout string `xml:"timeout,omitempty"`
Retry *Retry `xml:"retry,omitempty"`
NodeFilter *JobNodeFilter `xml:"nodefilters,omitempty"`
Orchestrator *JobOrchestrator `xml:"orchestrator,omitempty"`

/* If Dispatch is enabled, nodesSelectedByDefault is always present with true/false.
* by this reason omitempty cannot be present.
Expand Down Expand Up @@ -317,6 +318,20 @@ type JobNodeFilter struct {
ExcludePrecedence bool `xml:"excludeprecedence,omitempty"`
}

// JobOrchestratorConfig Contains the options for the Job Orchestrators
type JobOrchestratorConfig struct {
Count int `xml:"count,omitempty"`
Percent int `xml:"percent,omitempty"`
Attribute string `xml:"attribute,omitempty"`
Sort string `xml:"sort,omitempty"`
}

// JobOrchestrator describes how to schedule the jobs, in what order, and on how many nodes
type JobOrchestrator struct {
Config JobOrchestratorConfig `xml:"configuration"`
Type string `xml:"type"`
}

type jobImportResults struct {
Succeeded jobImportResultsCategory `xml:"succeeded"`
Failed jobImportResultsCategory `xml:"failed"`
Expand Down Expand Up @@ -511,14 +526,11 @@ func (c *JobValueChoices) UnmarshalXMLAttr(attr xml.Attr) error {

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

func (a *JobCommandJobRefArguments) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
Expand Down
85 changes: 80 additions & 5 deletions rundeck/resource_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,43 @@ func resourceRundeckJob() *schema.Resource {
Type: schema.TypeBool,
Optional: true,
},

"timeout": {
Type: schema.TypeString,
Optional: true,
},
"orchestrator": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Required: true,
Description: "Option of `subset`, `rankTiered`, `maxPercentage`, `orchestrator-highest-lowest-attribute`",
},
"count": {
Type: schema.TypeInt,
Optional: true,
Description: "Value for the subset orchestrator",
},
"percent": {
Type: schema.TypeInt,
Optional: true,
Description: "Value for the maxPercentage orchestrator",
},
"attribute": {
Type: schema.TypeString,
Optional: true,
Description: "The Node Attribute that shoud be used to rank nodes in High/Low Orchestrator.",
},
"sort": {
Type: schema.TypeString,
Optional: true,
Description: "Option of `highest` or `lowest` for High/Low Orchestrator",
},
},
},
},

"schedule": {
Type: schema.TypeString,
Expand Down Expand Up @@ -627,6 +659,49 @@ func jobFromResourceData(d *schema.ResourceData) (*JobDetail, error) {
job.Dispatch.SuccessOnEmptyNodeFilter = successOnEmpty.(bool)
}

orchList := d.Get("orchestrator").([]interface{})
if len(orchList) > 1 {
return nil, fmt.Errorf("rundeck command may have no more than one orchestrator")
}
for _, orch := range orchList {
orchMap := orch.(map[string]interface{})
job.Orchestrator = &JobOrchestrator{
Type: orchMap["type"].(string),
Config: JobOrchestratorConfig{},
}
orchType := orchMap["type"].(string)
if orchType == "orchestrator-highest-lowest-attribute" {
orchAttr := orchMap["attribute"]
if orchAttr != nil {
job.Orchestrator.Config.Attribute = orchAttr.(string)
} else {
return nil, fmt.Errorf("high Low Orchestrator must include an attribute to sort against")
}
orchSort := orchMap["sort"]
if orchSort != nil {
job.Orchestrator.Config.Sort = orchSort.(string)
} else {
return nil, fmt.Errorf("high low orchestrator must include sort direction of `high` or `low`")
}
}
if orchType == "subset" {
orchCount := orchMap["count"]
if orchCount != nil {
job.Orchestrator.Config.Count = orchCount.(int)
} else {
return nil, fmt.Errorf("subset Orchestrator requires count setting")
}
}
if orchType == "maxPercentage" {
orchPct := orchMap["percent"]
if orchPct != nil {
job.Orchestrator.Config.Percent = orchPct.(int)
} else {
return nil, fmt.Errorf("max Percentage Orchestrator requires a percent integer configuration")
}
}
}

sequence := &JobCommandSequence{
ContinueOnError: d.Get("continue_on_error").(bool),
OrderingStrategy: d.Get("command_ordering_strategy").(string),
Expand Down Expand Up @@ -687,11 +762,11 @@ func jobFromResourceData(d *schema.ResourceData) (*JobDetail, error) {
ValueIsExposedToScripts: optionMap["exposed_to_scripts"].(bool),
StoragePath: optionMap["storage_path"].(string),
}
if option.StoragePath != "" && option.ObscureInput == false {
return nil, fmt.Errorf("Argument \"obscure_input\" must be set to `true` when \"storage_path\" is not empty.")
if option.StoragePath != "" && !option.ObscureInput {
return nil, fmt.Errorf("argument \"obscure_input\" must be set to `true` when \"storage_path\" is not empty")
}
if option.ValueIsExposedToScripts && option.ObscureInput == false {
return nil, fmt.Errorf("Argument \"obscure_input\" must be set to `true` when \"exposed_to_scripts\" is set to true.")
if option.ValueIsExposedToScripts && !option.ObscureInput {
return nil, fmt.Errorf("argument \"obscure_input\" must be set to `true` when \"exposed_to_scripts\" is set to true")
}

for _, iv := range optionMap["value_choices"].([]interface{}) {
Expand Down
Loading