-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
229 lines (215 loc) · 10.4 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package main
import (
"code.cloudfoundry.org/cli/cf/i18n"
"code.cloudfoundry.org/cli/cf/terminal"
"code.cloudfoundry.org/cli/plugin"
plugin_models "code.cloudfoundry.org/cli/plugin/models"
"code.cloudfoundry.org/cli/util/configv3"
"flag"
"fmt"
"github.com/rabobank/scheduler-plugin/version"
"net/http"
"os"
"time"
)
const (
HttpTimeoutDefault = 5
CreateJobHelpText = "creates a schedulable job"
CreateJobUsage = "create-job APP_NAME JOB_NAME COMMAND [MEMORY_IN_MB] [DISK_IN_MB]"
ListJobsHelpText = "lists all schedulable jobs"
ListJobsUsage = "jobs"
DeleteJobHelpText = "deletes a schedulable job"
DeleteJobUsage = "delete-job [--force] JOB_NAME"
RunJobHelpText = "runs a job"
RunJobUsage = "run-job JOB_NAME"
CreateCallHelpText = "creates a schedulable call"
CreateCallUsage = "create-call [--auth-header AUTH-HEADER] APP_NAME CALL_NAME URL"
ListCallsHelpText = "lists all schedulable calls"
ListCallsUsage = "calls"
DeleteCallHelpText = "deletes a schedulable call"
DeleteCallUsage = "delete-call [--force] CALL_NAME"
RunCallHelpText = "runs a call"
RunCallUsage = "run-call CALL_NAME"
CreateJobScheduleHelpText = "schedules a job"
CreateJobScheduleUsage = "schedule-job JOB_NAME CRON_EXPRESSION"
ListJobSchedulesHelpText = "lists all job schedules"
ListJobSchedulesUsage = "job-schedules"
DeleteJobScheduleHelpText = "deletes a schedule for a job"
DeleteJobScheduleUsage = "delete-job-schedule JOB_NAME SCHEDULE_GUID"
CreateCallScheduleHelpText = "schedules a call"
CreateCallScheduleUsage = "schedule-call CALL_NAME CRON_EXPRESSION"
ListCallSchedulesHelpText = "lists all call schedules"
ListCallSchedulesUsage = "call-schedules"
DeleteCallScheduleHelpText = "deletes a schedule for a call"
DeleteCallScheduleUsage = "delete-call-schedule CALL_NAME SCHEDULE_GUID"
ListJobHistoriesHelpText = "lists the history for a scheduled job"
ListJobHistoriesUsage = "job-history JOB_NAME"
ListCallHistoriesHelpText = "lists the history for a scheduled call"
ListCallHistoriesUsage = "call-history CALL_NAME"
)
var (
accessToken string
currentOrg plugin_models.Organization
currentSpace plugin_models.Space
currentUser string
serviceInstance plugin_models.GetService_Model
requestHeader http.Header
httpClient http.Client
FlagForce bool
FlagAuthHeader string
FlagTimeout int
FlagMemoryInMB int
FlagDiskInMB int
)
// Run must be implemented by any plugin because it is part of the plugin interface defined by the core CLI.
//
// Run(....) is the entry point when the core CLI is invoking a command defined by a plugin.
// The first parameter, plugin.CliConnection, is a struct that can be used to invoke cli commands. The second parameter, args, is a slice of strings.
// args[0] will be the name of the command, and will be followed by any additional arguments a cli user typed in.
//
// Any error handling should be handled with the plugin itself (this means printing user facing errors).
// The CLI will exit 0 if the plugin exits 0 and will exit 1 should the plugin exits nonzero.
func (c *SchedulerPlugin) Run(cliConnection plugin.CliConnection, args []string) {
pluginFlagSet := flag.NewFlagSet("scheduler-plugin", flag.ExitOnError)
pluginFlagSet.BoolVar(&FlagForce, "force", false, "exit with rc=0, even if the command fails (only applicable for deletes)")
pluginFlagSet.StringVar(&FlagAuthHeader, "auth-header", "", "the authorization header to use on the http call (only applicable for create-call)")
pluginFlagSet.IntVar(&FlagTimeout, "timeout", HttpTimeoutDefault, "the timeout (in secs) to use on http calls")
pluginFlagSet.IntVar(&FlagMemoryInMB, "memory_in_mb", 0, "memory in MB to use for the job (only applicable for create-job)")
pluginFlagSet.IntVar(&FlagDiskInMB, "disk_in_mb", 0, "disk in MB to use for the job (only applicable for create-job)")
if err := pluginFlagSet.Parse(args[1:]); err != nil {
fmt.Printf("failed to parse arguments: %s", err)
}
httpClient = http.Client{Timeout: time.Duration(FlagTimeout) * time.Second}
if args[0] != "install-plugin" && args[0] != "CLI-MESSAGE-UNINSTALL" {
preCheck(cliConnection)
requestHeader = map[string][]string{"Content-Type": {"application/json"}, "Authorization": {accessToken}}
}
switch args[0] {
case "create-job":
createJob(cliConnection, pluginFlagSet.Args())
case "jobs":
jobs(pluginFlagSet.Args())
case "delete-job":
deleteJob(pluginFlagSet.Args())
case "create-call":
createCall(cliConnection, pluginFlagSet.Args())
case "calls":
calls(pluginFlagSet.Args())
case "delete-call":
deleteCall(pluginFlagSet.Args())
case "schedule-job":
createJobSchedule(pluginFlagSet.Args())
case "job-schedules":
jobSchedules(pluginFlagSet.Args())
case "delete-job-schedule":
deleteJobSchedule(pluginFlagSet.Args())
case "schedule-call":
createCallSchedule(pluginFlagSet.Args())
case "call-schedules":
callSchedules(pluginFlagSet.Args())
case "delete-call-schedule":
deleteCallSchedule(pluginFlagSet.Args())
case "job-history":
jobHistories(pluginFlagSet.Args())
case "call-history":
callHistories(pluginFlagSet.Args())
case "run-call":
runCall(pluginFlagSet.Args())
case "run-job":
runJob(pluginFlagSet.Args())
}
}
// GetMetadata returns a PluginMetadata struct. The first field, Name, determines the name of the plugin which should generally be without spaces.
// If there are spaces in the name a user will need to properly quote the name during uninstall otherwise the name will be treated as separate arguments.
// The second value is a slice of Command structs. Our slice only contains one Command Struct, but could contain any number of them.
// The first field Name defines the command `cf basic-plugin-command` once installed into the CLI.
// The second field, HelpText, is used by the core CLI to display help information to the user in the core commands `cf help`, `cf`, or `cf -h`.
func (c *SchedulerPlugin) GetMetadata() plugin.PluginMetadata {
return plugin.PluginMetadata{
Name: "Scheduler",
Version: plugin.VersionType{Major: version.GetMajorVersion(), Minor: version.GetMinorVersion(), Build: version.GetPatchVersion()},
MinCliVersion: plugin.VersionType{Major: 6, Minor: 7, Build: 0},
Commands: []plugin.Command{
{Name: "create-job", HelpText: CreateJobHelpText, UsageDetails: plugin.Usage{Usage: CreateJobUsage}},
{Name: "jobs", HelpText: ListJobsHelpText, UsageDetails: plugin.Usage{Usage: ListJobsUsage}},
{Name: "delete-job", HelpText: DeleteJobHelpText, UsageDetails: plugin.Usage{Usage: DeleteJobUsage}},
{Name: "create-call", HelpText: CreateCallHelpText, UsageDetails: plugin.Usage{Usage: CreateCallUsage}},
{Name: "calls", HelpText: ListCallsHelpText, UsageDetails: plugin.Usage{Usage: ListCallsUsage}},
{Name: "delete-call", HelpText: DeleteCallHelpText, UsageDetails: plugin.Usage{Usage: DeleteCallUsage}},
{Name: "schedule-job", HelpText: CreateJobScheduleHelpText, UsageDetails: plugin.Usage{Usage: CreateJobScheduleUsage}},
{Name: "job-schedules", HelpText: ListJobSchedulesHelpText, UsageDetails: plugin.Usage{Usage: ListJobSchedulesUsage}},
{Name: "delete-job-schedule", HelpText: DeleteJobScheduleHelpText, UsageDetails: plugin.Usage{Usage: DeleteJobScheduleUsage}},
{Name: "schedule-call", HelpText: CreateCallScheduleHelpText, UsageDetails: plugin.Usage{Usage: CreateCallScheduleUsage}},
{Name: "call-schedules", HelpText: ListCallSchedulesHelpText, UsageDetails: plugin.Usage{Usage: ListCallSchedulesUsage}},
{Name: "delete-call-schedule", HelpText: DeleteCallScheduleHelpText, UsageDetails: plugin.Usage{Usage: DeleteCallScheduleUsage}},
{Name: "job-history", HelpText: ListJobHistoriesHelpText, UsageDetails: plugin.Usage{Usage: ListJobHistoriesUsage}},
{Name: "call-history", HelpText: ListCallHistoriesHelpText, UsageDetails: plugin.Usage{Usage: ListCallHistoriesUsage}},
{Name: "run-call", HelpText: RunCallHelpText, UsageDetails: plugin.Usage{Usage: RunCallUsage}},
{Name: "run-job", HelpText: RunJobHelpText, UsageDetails: plugin.Usage{Usage: RunJobUsage}},
},
}
}
// preCheck Does all common validations, like being logged in, and having a targeted org and space, and if there is an instance of the scheduler-service.
func preCheck(cliConnection plugin.CliConnection) {
config, _ := configv3.LoadConfig()
i18n.T = i18n.Init(config)
var schedulerService plugin_models.GetService_Model
loggedIn, err := cliConnection.IsLoggedIn()
if err != nil || !loggedIn {
fmt.Println(terminal.NotLoggedInText())
os.Exit(1)
}
currentUser, _ = cliConnection.Username()
hasOrg, err := cliConnection.HasOrganization()
if err != nil || !hasOrg {
fmt.Println(terminal.FailureColor("please target your org/space first"))
os.Exit(1)
}
org, _ := cliConnection.GetCurrentOrg()
currentOrg = org
hasSpace, err := cliConnection.HasSpace()
if err != nil || !hasSpace {
fmt.Println(terminal.FailureColor("please target your space first"))
os.Exit(1)
}
space, _ := cliConnection.GetCurrentSpace()
currentSpace = space
if accessToken, err = cliConnection.AccessToken(); err != nil {
fmt.Println(err)
os.Exit(1)
}
services, err := cliConnection.GetServices()
if err != nil {
fmt.Println(err)
os.Exit(1)
} else {
var schedulerServiceFound = false
var instanceName string
for _, service := range services {
if service.Service.Name == "scheduler" {
schedulerServiceFound = true
instanceName = service.Name
}
}
if !schedulerServiceFound {
fmt.Println(terminal.FailureColor("no scheduler service instance found, please create a scheduler service instance first"))
}
schedulerService, err = cliConnection.GetService(instanceName)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
serviceInstance = schedulerService
}
// Unlike most Go programs, the `Main()` function will not be used to run all of the commands provided in your plugin.
// Main will be used to initialize the plugin process, as well as any dependencies you might require for your plugin.
func main() {
// Any initialization for your plugin can be handled here
//
// Note: to run the plugin.Start method, we pass in a pointer to the struct implementing the interface defined at "code.cloudfoundry.org/cli/plugin/plugin.go"
//
// Note: The plugin's main() method is invoked at install time to collect metadata. The plugin will exit 0 and the Run([]string) method will not be invoked.
plugin.Start(new(SchedulerPlugin))
// Plugin code should be written in the Run([]string) method, ensuring the plugin environment is bootstrapped.
}