diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5b4efd0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +vendor/ linguist-generated=true +Gopkg.lock linguist-generated=true +Gopkg.sum linguist-generated=true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5b22bd7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup Go for use with actions + uses: actions/setup-go@v2 + with: + go-version: 1.15 + - name: Install goimports + run: go get golang.org/x/tools/cmd/goimports + - name: Set env with list of directories in repo containin go code + run: echo GO_USR_DIRS=$(go list -f {{.Dir}} ./... | grep -E -v "/gen-go/|/vendor/") >> $GITHUB_ENV + - name: Run goimports check + run: test -z `for d in $GO_USR_DIRS; do goimports -d "$d" | tee /dev/stderr; done` + - name: Run tests + run: go build -o australis *.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..672711c --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +debian/australis +debian/australis.debhelper.log +debian/debhelper-build-stamp +debian/files +debian/australis.substvars +build/ +dist/ +.idea/ + +# Use checksum database +go.sum + +.DS_Store diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..2c36ee7 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,75 @@ +1.0.6 (unreleased) + +1.0.5 + +* fetch mesos & aurora master nodes +* kill an instance from a job + +1.0.4 + +* fetch free capacity +* simulate task fitting - compute how many tasks can be fit in the remaining capacity + +1.0.3 + +* update CI to compile on PRs +* Add tier and production in task config +* Add fetch quota command +* Add priority into job config + +1.0.2 + +* Fixing broken Thrift dependency by bumping up backported version to thrift v0.13.2 + +1.0.1 + +* Added flag -m and --monitor that can be set in order to monitor a job creation or a job kill. By default monitor is set to true. + +1.0.0 + +* First stable release. + +0.1.1 + +* Removed support for building with dep +* Upgraded depdencies to their latest versions. +* gorealis v2 now lives in the aurora-scheduler organization and dependencies have been updated to reflect that. + +0.1.0 + +* Adding support for drain sub-command to take in JSON list from stdin or from a specified file. +* Added flags `json-file` and `json` to drain, maintenance, and sla-drain. + +0.0.9 + +* Added ability to create jobs which contain an executorless docker container. +* Sla-aware draining sub-command has been simplified. Instead of having a count/percentage + subcommand, it now has a flag for each of these options. The count and percentage flag are + mutually exclusive, and one of them has to be set. + +0.0.8 + +* Updated default timeouts and durations for sla-aware draining. +* Added monitor verb along with hosts noun. +* Fixed bug with monitor not using the correct default values for sla-aware drain policies. + +0.0.7 + +* Initial migration to gorealis v2 +* Implemented first version of create feature which takes in a YAML file. +* Added new noun to fetch status called task. Task also has two subcommands, status and config. + +0.0.6 + +* Added auto-completion to the deb file. +* Added set verb and quota noun to set quota resource for certain roles. +* Added JSON output as an option for all commands. + +0.0.5 + +* Backup and snapshot commands have now been moved to under the force subcommand as these are expensive operations +and the subcommand should reflect that. +* Cobra library upgrade. +* Added version command. +* Added ability to use config config file. By default this file will be located in /etc/aurora/australis.yml +* Changed insecureSkipVerify to skipCertVerification. diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index 55aa189..0000000 --- a/Gopkg.lock +++ /dev/null @@ -1,52 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - name = "git.apache.org/thrift.git" - packages = ["lib/go/thrift"] - revision = "b2a4d4ae21c789b689dd162deb819665567f481c" - version = "0.10.0" - -[[projects]] - name = "github.com/inconshreveable/mousetrap" - packages = ["."] - revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" - version = "v1.0" - -[[projects]] - branch = "SSLOverride" - name = "github.com/paypal/gorealis" - packages = [ - ".", - "gen-go/apache/aurora", - "response" - ] - revision = "d64a91784a16206c036048a5006a103ed7fe0d89" - -[[projects]] - name = "github.com/pkg/errors" - packages = ["."] - revision = "e881fd58d78e04cf6d0de1217f8707c8cc2249bc" - -[[projects]] - name = "github.com/samuel/go-zookeeper" - packages = ["zk"] - revision = "471cd4e61d7a78ece1791fa5faa0345dc8c7d5a5" - -[[projects]] - name = "github.com/spf13/cobra" - packages = ["."] - revision = "0c34d16c3123764e413b9ed982ada58b1c3d53ea" - -[[projects]] - name = "github.com/spf13/pflag" - packages = ["."] - revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" - version = "v1.0.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "605455afaa36eb3474c79fbff14ae9755c5acf95d947da68ca1bc376c29f4245" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index 126724c..0000000 --- a/Gopkg.toml +++ /dev/null @@ -1,13 +0,0 @@ -required = ["git.apache.org/thrift.git/lib/go/thrift"] - -[[constraint]] - name = "github.com/paypal/gorealis" - branch = "develop" - -[[constraint]] - name = "github.com/spf13/cobra" - revision = "0c34d16c3123764e413b9ed982ada58b1c3d53ea" - -[[constraint]] - name = "git.apache.org/thrift.git" - version = "0.10.0" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9c8f3ea --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md index f141f34..d2db695 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,17 @@ # Australis -A light-weight client for [Apache Aurora](https://aurora.apache.org/) built using [gorealis](https://github.com/paypal/gorealis). +A light-weight client for [Aurora Scheduler](https://aurora-scheduler.github.io/) built using [gorealis](https://github.com/aurora-scheduler/gorealis). -## Usage - -``` -Usage: - australis [command] - -Available Commands: - create Create an Aurora Job - fetch Fetch information from Aurora - help Help about any command - kill Kill an Aurora Job - start Start a service or maintenance on a host (DRAIN). - stop Stop a service or maintenance on a host (DRAIN). - -Flags: - -h, --help help for australis - -p, --password string Password to use for API authentication - -s, --scheduler_addr string Aurora Scheduler's address. - -u, --username string Username to use for API authentication - -z, --zookeeper string Zookeeper node(s) where Aurora stores information. - -Use "australis [command] --help" for more information about a command. -``` - -## Sample commands: - -### Fetching current leader -`australis fetch leader [ZK NODE 1] [ZK NODE 2]...[ZK NODE N]` - -### Setting host to DRAIN: -`australis start drain [HOST 1] [HOST 2]...[HOST N]` - -### Taking hosts out of DRAIN (End maintenance): -`australis stop drain [HOST 1] [HOST 2]...[HOST N]` +## Usage +See the [documentation](docs/australis.md) for more information. ## Status -Australis is a work in progress and does not support all the features of Apache Aurora. +Australis is a work in progress and does not support all the features of Aurora Scheduler. + +### Build locally +This project uses go mods. To build locally run: + +`$ go build -o australis main.go` + +### Building debian package +From the inside of the deb-packaging folder, run [build_deb.sh](deb-packaging/build_deb.sh) diff --git a/cmd/completion.go b/cmd/completion.go new file mode 100644 index 0000000..258a45f --- /dev/null +++ b/cmd/completion.go @@ -0,0 +1,44 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(completionCmd) + + completionCmd.Hidden = true + completionCmd.Flags().StringVar(&filename, "filename", "australis.completion.sh", "Path and name of the autocompletion file.") +} + +var completionCmd = &cobra.Command{ + Use: "autocomplete", + Short: "Create auto completion for bash.", + Long: `Create auto completion bash file for australis. Auto completion file must be placed in the correct +directory in order for bash to pick up the definitions. + +Copy australis.completion.sh into the correct folder and rename to australis + +In Linux, this directory is usually /etc/bash_completion.d/ +In MacOS this directory is $(brew --prefix)/etc/bash_completion.d if auto completion was install through brew. +`, + PersistentPreRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PersistentPostRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + Run: func(cmd *cobra.Command, args []string) { + rootCmd.GenBashCompletionFile(filename) + }, +} diff --git a/cmd/create.go b/cmd/create.go index 9ebdfcd..6ea8b93 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -1,27 +1,61 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package cmd import ( - "fmt" - + "github.com/aurora-scheduler/australis/internal" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(createCmd) - createCmd.Flags().StringVarP(&env, "environment", "e", "", "Aurora Environment") - createCmd.Flags().StringVarP(&role, "role", "r", "", "Aurora Role") - createCmd.Flags().StringVarP(&name, "name", "n", "", "Aurora Name") - createCmd.MarkFlagRequired("environment") - createCmd.MarkFlagRequired("role") - createCmd.MarkFlagRequired("name") + createCmd.Flags().BoolVarP(&monitor, "monitor", "m", true, "monitor the result after sending the command") } var createCmd = &cobra.Command{ Use: "create", Short: "Create an Aurora Job", Run: createJob, + Args: cobra.RangeArgs(1, 2), } func createJob(cmd *cobra.Command, args []string) { - fmt.Println("Not implemented yet.") + job, err := internal.UnmarshalJob(args[0]) + + if err != nil { + log.Fatalln(err) + } + + auroraJob, err := job.ToRealis() + if err != nil { + log.Fatalln(err) + } + + if err := client.CreateJob(auroraJob); err != nil { + log.Fatal("unable to create Aurora job: ", err) + } + + if monitor { + if ok, monitorErr := client.MonitorInstances(auroraJob.JobKey(), + auroraJob.GetInstanceCount(), + 5, + 50); !ok || monitorErr != nil { + if err := client.KillJob(auroraJob.JobKey()); err != nil { + log.Fatal(monitorErr, err) + } + log.Fatal(monitorErr) + } + } } diff --git a/cmd/docs.go b/cmd/docs.go new file mode 100644 index 0000000..b3fde4f --- /dev/null +++ b/cmd/docs.go @@ -0,0 +1,38 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +func init() { + rootCmd.AddCommand(docsCmd) + docsCmd.Hidden = true +} + +var docsCmd = &cobra.Command{ + Use: "docs", + Short: "Generate documents in markdown format for Australis.", + PersistentPreRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PersistentPostRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + Run: func(cmd *cobra.Command, args []string) { + err := doc.GenMarkdownTree(rootCmd, "./docs") + if err != nil { + log.Fatal(err) + } + }, +} diff --git a/cmd/fetch.go b/cmd/fetch.go index a7c6bba..fbdc309 100644 --- a/cmd/fetch.go +++ b/cmd/fetch.go @@ -1,27 +1,179 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package cmd import ( + "encoding/json" + "errors" "fmt" - "os" + "io/ioutil" + "net/http" + "strings" - "github.com/paypal/gorealis" - "github.com/paypal/gorealis/gen-go/apache/aurora" + "github.com/aurora-scheduler/australis/internal" + realis "github.com/aurora-scheduler/gorealis/v2" + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" "github.com/spf13/cobra" + "github.com/spf13/pflag" ) +const ( + localAgentStateURL = "http://127.0.0.1:5051/state" +) + +type mesosAgentState struct { + Flags mesosAgentFlags `json:"flags,omitempty"` +} + +type mesosAgentFlags struct { + Master string `json:"master,omitempty"` + hasMaster bool // indicates if the master flag contains direct Master's address +} + func init() { rootCmd.AddCommand(fetchCmd) // Sub-commands // Fetch Task Config - fetchCmd.AddCommand(taskConfigCmd) - taskConfigCmd.Flags().StringVarP(&env, "environment", "e", "", "Aurora Environment") - taskConfigCmd.Flags().StringVarP(&role, "role", "r", "", "Aurora Role") - taskConfigCmd.Flags().StringVarP(&name, "name", "n", "", "Aurora Name") + fetchCmd.AddCommand(fetchTaskCmd) + + // Fetch Task Config + fetchTaskCmd.AddCommand(taskConfigCmd) + taskConfigCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + taskConfigCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + taskConfigCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + + // Fetch Task Status + fetchTaskCmd.AddCommand(taskStatusCmd) + taskStatusCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + taskStatusCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + taskStatusCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + + /* Fetch Leader */ + leaderCmd.Flags().String("zkPath", "/aurora/scheduler", "Zookeeper node path where leader election happens") - // Fetch Leader fetchCmd.AddCommand(leaderCmd) + + // Hijack help function to hide unnecessary global flags + help := leaderCmd.HelpFunc() + leaderCmd.SetHelpFunc(func(cmd *cobra.Command, s []string) { + if cmd.HasInheritedFlags() { + cmd.InheritedFlags().VisitAll(func(f *pflag.Flag) { + if f.Name != "logLevel" { + f.Hidden = true + } + }) + } + help(cmd, s) + }) + + mesosLeaderCmd.Flags().String("zkPath", "/mesos", "Zookeeper node path where mesos leader election happens") + mesosCmd.AddCommand(mesosLeaderCmd) + + fetchCmd.AddCommand(mesosCmd) + + // Hijack help function to hide unnecessary global flags + mesosCmd.SetHelpFunc(func(cmd *cobra.Command, s []string) { + if cmd.HasInheritedFlags() { + cmd.InheritedFlags().VisitAll(func(f *pflag.Flag) { + if f.Name != "logLevel" { + f.Hidden = true + } + }) + } + help(cmd, s) + }) + + /* Fetch Master nodes/Leader */ + masterCmd.Flags().String("zkPath", "/aurora/scheduler", "Zookeeper node path to get master nodes/leader") + + fetchCmd.AddCommand(masterCmd) + + // Hijack help function to hide unnecessary global flags + masterCmd.SetHelpFunc(func(cmd *cobra.Command, s []string) { + if cmd.HasInheritedFlags() { + cmd.InheritedFlags().VisitAll(func(f *pflag.Flag) { + if f.Name != "logLevel" { + f.Hidden = true + } + }) + } + help(cmd, s) + }) + + mesosMasterCmd.Flags().String("zkPath", "/mesos", "Zookeeper node path to get mesos master nodes/leader") + mesosCmd.AddCommand(mesosMasterCmd) + + // Hijack help function to hide unnecessary global flags + mesosMasterCmd.SetHelpFunc(func(cmd *cobra.Command, s []string) { + if cmd.HasInheritedFlags() { + cmd.InheritedFlags().VisitAll(func(f *pflag.Flag) { + if f.Name != "logLevel" { + f.Hidden = true + } + }) + } + help(cmd, s) + }) + + // Fetch jobs + fetchJobsCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + fetchCmd.AddCommand(fetchJobsCmd) + + // Fetch Status + fetchCmd.AddCommand(fetchStatusCmd) + + // fetch quota + fetchCmd.AddCommand(fetchQuotaCmd) + + // fetch capacity + fetchCmd.AddCommand(fetchAvailCapacityCmd) + + // Hijack help function to hide unnecessary global flags + fetchAvailCapacityCmd.SetHelpFunc(func(cmd *cobra.Command, s []string) { + if cmd.HasInheritedFlags() { + cmd.InheritedFlags().VisitAll(func(f *pflag.Flag) { + if f.Name != "logLevel" { + f.Hidden = true + } + }) + } + help(cmd, s) + }) + + // fetch tasks with status + fetchCmd.AddCommand(fetchTasksWithStatusCmd) + + fetchTasksWithStatusCmd.Flags().StringVarP(taskStatus, "status", "x", "", "Task Status") + fetchTasksWithStatusCmd.MarkFlagRequired("status") + fetchTasksWithStatusCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + fetchTasksWithStatusCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + fetchTasksWithStatusCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + + // Hijack help function to hide unnecessary global flags + fetchTasksWithStatusCmd.SetHelpFunc(func(cmd *cobra.Command, s []string) { + if cmd.HasInheritedFlags() { + cmd.InheritedFlags().VisitAll(func(f *pflag.Flag) { + if f.Name != "logLevel" { + f.Hidden = true + } + }) + } + help(cmd, s) + }) } var fetchCmd = &cobra.Command{ @@ -29,53 +181,505 @@ var fetchCmd = &cobra.Command{ Short: "Fetch information from Aurora", } +var fetchTaskCmd = &cobra.Command{ + Use: "task", + Short: "Task information from Aurora", +} + var taskConfigCmd = &cobra.Command{ Use: "config", Short: "Fetch a list of task configurations from Aurora.", Long: `To be written.`, - Run: fetchTasks, + Run: fetchTasksConfig, +} + +var taskStatusCmd = &cobra.Command{ + Use: "status", + Short: "Fetch task status for a Job key.", + Long: `To be written.`, + Run: fetchTasksStatus, } var leaderCmd = &cobra.Command{ - Use: "leader", - PersistentPreRun: func(cmd *cobra.Command, args []string) {}, //We don't need a realis client for this cmd - PersistentPostRun: func(cmd *cobra.Command, args []string) {}, //We don't need a realis client for this cmd - Short: "Fetch current Aurora leader given Zookeeper nodes. Pass Zookeeper nodes separated by a space as an argument to this command.", - Long: `To be written.`, - Run: fetchLeader, + Use: "leader [zkNode0, zkNode1, ...zkNodeN]", + PersistentPreRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PersistentPostRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PreRun: setConfig, + Args: cobra.MinimumNArgs(1), + Short: "Fetch current Aurora leader given Zookeeper nodes. ", + Long: `Gets the current leading aurora scheduler instance using information from Zookeeper path. +Pass Zookeeper nodes separated by a space as an argument to this command.`, + Run: fetchLeader, } -func fetchTasks(cmd *cobra.Command, args []string) { - fmt.Printf("Fetching job configuration for [%s/%s/%s] \n", env, role, name) +var masterCmd = &cobra.Command{ + Use: "master [zkNode0 zkNode1 ...zkNodeN]", + PersistentPreRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PersistentPostRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PreRun: setConfig, + Args: cobra.MinimumNArgs(1), + Short: "Fetch current Aurora master nodes/leader given Zookeeper nodes. ", + Long: `Gets the current aurora master nodes/leader using information from Zookeeper path. +Pass Zookeeper nodes separated by a space as an argument to this command.`, + Run: fetchMaster, +} +var mesosCmd = &cobra.Command{ + Use: "mesos", + PreRun: setConfig, + Short: "Fetch information from Mesos.", +} + +var mesosLeaderCmd = &cobra.Command{ + Use: "leader [zkNode0, zkNode1, ...zkNodeN]", + PersistentPreRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PersistentPostRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PreRun: setConfig, + Short: "Fetch current Mesos-master leader given Zookeeper nodes.", + Long: `Gets the current leading Mesos-master instance using information from Zookeeper path. +Pass Zookeeper nodes separated by a space as an argument to this command. If no nodes are provided, +it fetches leader from local Mesos agent or Zookeeper`, + Run: fetchMesosLeader, +} + +var mesosMasterCmd = &cobra.Command{ + Use: "master [zkNode0 zkNode1 ...zkNodeN]", + PersistentPreRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PersistentPostRun: func(cmd *cobra.Command, args []string) {}, // We don't need a realis client for this cmd + PreRun: setConfig, + Short: "Fetch current Mesos-master nodes/leader given Zookeeper nodes.", + Long: `Gets the current Mesos-master instances using information from Zookeeper path. +Pass Zookeeper nodes separated by a space as an argument to this command. If no nodes are provided, +it fetches Mesos-master nodes/leader from local Mesos agent or Zookeeper`, + Run: fetchMesosMaster, +} + +var fetchJobsCmd = &cobra.Command{ + Use: "jobs", + Short: "Fetch a list of task Aurora running under a role.", + Long: `To be written.`, + Run: fetchJobs, +} + +var fetchStatusCmd = &cobra.Command{ + Use: "status", + Short: "Fetch the maintenance status of a node from Aurora", + Long: `This command will print the actual status of the mesos agent nodes in Aurora server`, + Run: fetchHostStatus, +} + +var fetchQuotaCmd = &cobra.Command{ + Use: "quota", + Short: "Fetch the quotas of given roles", + Long: `This command will print list of resource quotas with the aggregated resources for the given roles`, + Run: fetchQuota, +} + +var fetchAvailCapacityCmd = &cobra.Command{ + Use: "capacity", + PreRun: setConfig, + Short: "Fetch capacity report", + Long: `This command will show detailed capacity report of the cluster`, + Run: fetchAvailCapacity, +} + +var fetchTasksWithStatusCmd = &cobra.Command{ + Use: "tasks", + Short: "Fetch tasks with status", + Long: `This command will return the list of tasks with a given status`, + Run: fetchTasksWithStatus, +} + +func fetchTasksConfig(cmd *cobra.Command, args []string) { + log.Infof("Fetching job configuration for [%s/%s/%s] \n", *env, *role, *name) + + // Task Query takes nil for values it shouldn't need to match against. + // This allows us to potentially more expensive calls for specific environments, roles, or job names. + if *env == "" { + env = nil + } + if *role == "" { + role = nil + } + if *role == "" { + role = nil + } //TODO: Add filtering down by status taskQuery := &aurora.TaskQuery{Environment: env, Role: role, JobName: name} tasks, err := client.GetTasksWithoutConfigs(taskQuery) if err != nil { - fmt.Printf("error: %+v\n", err.Error()) - os.Exit(1) + log.Fatalf("error: %+v", err) } - for _, t := range tasks { - fmt.Println(t) + if toJson { + fmt.Println(internal.ToJSON(tasks)) + } else { + for _, t := range tasks { + fmt.Println(t) + } + } +} + +func fetchTasksStatus(cmd *cobra.Command, args []string) { + log.Infof("Fetching task status for [%s/%s/%s] \n", *env, *role, *name) + + // Task Query takes nil for values it shouldn't need to match against. + // This allows us to potentially more expensive calls for specific environments, roles, or job names. + if *env == "" { + env = nil + } + if *role == "" { + role = nil + } + if *role == "" { + role = nil + } + // TODO(rdelvalle): Add filtering down by status + taskQuery := &aurora.TaskQuery{ + Environment: env, + Role: role, + JobName: name, + Statuses: aurora.LIVE_STATES} + + tasks, err := client.GetTaskStatus(taskQuery) + if err != nil { + log.Fatalf("error: %+v", err) + } + + if toJson { + fmt.Println(internal.ToJSON(tasks)) + } else { + for _, t := range tasks { + fmt.Println(t) + } + } +} + +func fetchHostStatus(cmd *cobra.Command, args []string) { + log.Infof("Fetching maintenance status for %v \n", args) + result, err := client.MaintenanceStatus(args...) + if err != nil { + log.Fatalf("error: %+v\n", err) + } + + if toJson { + fmt.Println(internal.ToJSON(result.Statuses)) + } else { + for _, k := range result.GetStatuses() { + fmt.Printf("Result: %s:%s\n", k.Host, k.Mode) + } } } func fetchLeader(cmd *cobra.Command, args []string) { - fmt.Printf("Fetching leader from %v \n", args) + log.Infof("Fetching leader from %v \n", args) if len(args) < 1 { - fmt.Println("At least one Zookeper node address must be passed in.") - os.Exit(1) + log.Fatalln("At least one Zookeeper node address must be passed in.") } - url, err := realis.LeaderFromZKOpts(realis.ZKEndpoints(args...), realis.ZKPath("/aurora/scheduler")) + url, err := realis.LeaderFromZKOpts(realis.ZKEndpoints(args...), realis.ZKPath(cmd.Flag("zkPath").Value.String())) if err != nil { - fmt.Printf("error: %+v\n", err.Error()) - os.Exit(1) + log.Fatalf("error: %+v\n", err) } - fmt.Print(url) + fmt.Println(url) +} + +func fetchMesosLeader(cmd *cobra.Command, args []string) { + if len(args) < 1 { + mesosAgentFlags, err := fetchMasterFromAgent(localAgentStateURL) + if err != nil || mesosAgentFlags.Master == "" { + log.Debugf("unable to fetch Mesos leader via local Mesos agent: %v", err) + args = append(args, "localhost") + } else if mesosAgentFlags.hasMaster { + fmt.Println(mesosAgentFlags.Master) + return + } else { + args = append(args, strings.Split(mesosAgentFlags.Master, ",")...) + } + } + log.Infof("Fetching Mesos-master leader from Zookeeper node(s): %v \n", args) + + url, err := realis.MesosFromZKOpts(realis.ZKEndpoints(args...), realis.ZKPath(cmd.Flag("zkPath").Value.String())) + + if err != nil { + log.Fatalf("error: %+v\n", err) + } + + fmt.Println(url) +} + +func fetchMaster(cmd *cobra.Command, args []string) { + log.Infof("Fetching master nodes from %v \n", args) + + if len(args) < 1 { + log.Fatalln("At least one Zookeeper node address must be passed in.") + } + + masterMap, err := realis.MasterNodesFromZKOpts(realis.ZKEndpoints(args...), realis.ZKPath(cmd.Flag("zkPath").Value.String())) + + if err != nil { + log.Fatalf("error: %+v\n", err) + } + + if toJson { + fmt.Println(internal.ToJSON(masterMap)) + } else { + for key, masterNodes := range masterMap { + for _, masterNode := range masterNodes { + fmt.Println(key + "=" + masterNode) + } + } + } +} + +func fetchMesosMaster(cmd *cobra.Command, args []string) { + if len(args) < 1 { + mesosAgentFlags, err := fetchMasterFromAgent(localAgentStateURL) + if err != nil || mesosAgentFlags.Master == "" { + log.Debugf("unable to fetch Mesos master nodes via local Mesos agent: %v", err) + args = append(args, "localhost") + } else { + args = append(args, strings.Split(mesosAgentFlags.Master, ",")...) + } + } + log.Infof("Fetching Mesos-master nodes from Zookeeper node(s): %v \n", args) + + mesosMasterMap, err := realis.MesosMasterNodesFromZKOpts(realis.ZKEndpoints(args...), realis.ZKPath(cmd.Flag("zkPath").Value.String())) + + if err != nil { + log.Fatalf("error: %+v\n", err) + } + if toJson { + fmt.Println(internal.ToJSON(mesosMasterMap)) + } else { + for key, mesosMasterNodes := range mesosMasterMap { + for _, mesosMasterNode := range mesosMasterNodes { + fmt.Println(key + "=" + mesosMasterNode) + } + } + } +} + +func fetchMasterFromAgent(url string) (mesosAgentFlags mesosAgentFlags, err error) { + resp, err := http.Get(url) + if err != nil { + return + } + if resp.StatusCode != 200 { + return + } + defer resp.Body.Close() + + state := &mesosAgentState{} + err = json.NewDecoder(resp.Body).Decode(state) + if err != nil { + return + } + mesosAgentFlags = state.Flags + err = updateMasterFlag(&mesosAgentFlags) + return +} + +/* + Master flag can be passed as one of : + host:port + zk://host1:port1,host2:port2,.../path + zk://username:password@host1:port1,host2:port2,.../path + file:///path/to/file + This function takes care of all the above cases and updates flags with parsed values +*/ +func updateMasterFlag(flags *mesosAgentFlags) error { + zkPathPrefix := "zk://" + filePathPrefix := "file://" + if strings.HasPrefix(flags.Master, zkPathPrefix) { + beginIndex := len(zkPathPrefix) + if strings.Contains(flags.Master, "@") { + beginIndex = strings.Index(flags.Master, "@") + 1 + } + flags.Master = flags.Master[beginIndex:strings.LastIndex(flags.Master, "/")] + } else if strings.HasPrefix(flags.Master, filePathPrefix) { + content, err := ioutil.ReadFile(flags.Master) + if err != nil { + return err + } + if strings.Contains(string(content), filePathPrefix) { + return errors.New("invalid master file content") + } + flags.Master = string(content) + return updateMasterFlag(flags) + } else { + flags.hasMaster = true + } + return nil +} + +// TODO: Expand this to be able to filter by job name and environment. +func fetchJobs(cmd *cobra.Command, args []string) { + log.Infof("Fetching tasks under role: %s \n", *role) + + if *role == "" { + log.Fatalln("Role must be specified.") + } + + if *role == "*" { + log.Warnln("This is an expensive operation.") + *role = "" + } + + result, err := client.GetJobs(*role) + + if err != nil { + log.Fatalf("error: %+v", err) + } + + if toJson { + var configSlice []*aurora.JobConfiguration + + for _, config := range result.GetConfigs() { + configSlice = append(configSlice, config) + } + + fmt.Println(internal.ToJSON(configSlice)) + } else { + for jobConfig := range result.GetConfigs() { + fmt.Println(jobConfig) + } + } +} + +//fetchQuota gets quotas for roles in args +func fetchQuota(cmd *cobra.Command, args []string) { + for _, role := range args { + log.Infof("Fetching quota for role: %s \n", role) + result, err := client.GetQuota(role) + if err != nil { + log.Fatalf("error: %+v\n", err) + } + + if toJson { + fmt.Println(internal.ToJSON(result)) + } else { + fmt.Printf(" Quota: %v\n", internal.ToJSON(result.Quota.GetResources())) + fmt.Printf(" Aggregated Resources: \n") + fmt.Printf(" ProdSharedConsumption: %v\n", internal.ToJSON(result.ProdSharedConsumption.GetResources())) + fmt.Printf(" NonProdSharedConsumption: %v\n", + internal.ToJSON(result.NonProdSharedConsumption.GetResources())) + fmt.Printf(" ProdDedicatedConsumption: %v\n", + internal.ToJSON(result.ProdDedicatedConsumption.GetResources())) + fmt.Printf(" NonProdDedicatedConsumption: %v\n", + internal.ToJSON(result.NonProdDedicatedConsumption.GetResources())) + } + } +} + +//fetchAvailCapacity reports free capacity in details +func fetchAvailCapacity(cmd *cobra.Command, args []string) { + log.Infof("Fetching available capacity from %s/offers\n", client.GetSchedulerURL()) + + report, err := client.AvailOfferReport() + if err != nil { + log.Fatalf("error: %+v\n", err) + } + + // convert report to user-friendly structure + capacity := map[string]map[string]map[string]int64{} + for g, gv := range report { + if _, ok := capacity[g]; !ok { + capacity[g] = map[string]map[string]int64{} + } + + for r, rc := range gv { + if _, ok := capacity[g][r]; !ok { + capacity[g][r] = map[string]int64{} + } + + for v, c := range rc { + capacity[g][r][fmt.Sprint(v)] = c + } + } + } + + if toJson { + fmt.Println(internal.ToJSON(capacity)) + if err != nil { + log.Fatalf("error: %+v\n", err) + } + } else { + fmt.Println(capacity) + } +} + +//fetchTasksWithStatus returns lists of tasks for a given set of status +func fetchTasksWithStatus(cmd *cobra.Command, args []string) { + status := *taskStatus + + log.Infof("Fetching tasks for role/environment/job:[%s/%s/%s] \n", *role, *env, *name) + log.Infof("Fetching tasks for a given status: %v \n", status) + + // This Query takes nil for values it shouldn't need to match against. + // This allows us to potentially avoid expensive calls for specific environments, roles, or job names. + if *env == "" { + env = nil + } + if *role == "" { + role = nil + } + if *name == "" { + name = nil + } + // role needs to be specified if env is specified + if env != nil { + if role == nil { + log.Fatalln("Role must be specified when env is specified.") + } + } + // role or env needs to be specified if name is specified + if name != nil { + if role == nil && env == nil { + log.Fatalln("Role or env must be specified when name is specified.") + } + } + + queryStatuses, err := scheduleStatusFromString(status) + if err != nil { + log.Fatalf("error: %+v", err) + } + + taskQuery := &aurora.TaskQuery{Environment: env, Role: role, JobName: name, Statuses: queryStatuses} + + tasks, err := client.GetTasksWithoutConfigs(taskQuery) + if err != nil { + log.Fatalf("error: %+v", err) + } + + if toJson { + taskStatus := strings.ToUpper(status) + // convert task lists to a list of task id like role-env-name-[instance-id] + taskIdsMap := map[string][]string{} + var taskIds []string + for _, task := range tasks { + taskIds = append(taskIds, task.AssignedTask.TaskId) + } + taskIdsMap[taskStatus] = taskIds + fmt.Println(internal.ToJSON(taskIdsMap)) + } else { + fmt.Printf("Tasks for status %s:\n", strings.ToUpper(status)) + for _, t := range tasks { + fmt.Println(t.AssignedTask.TaskId) + } + } +} + +// Convert status slice into ScheduleStatus slice +func scheduleStatusFromString(status string) ([]aurora.ScheduleStatus, error) { + scheduleStatus, err := aurora.ScheduleStatusFromString(strings.ToUpper(status)) + if err != nil { + return nil, err + } + result := []aurora.ScheduleStatus{scheduleStatus} + return result, nil } diff --git a/cmd/force.go b/cmd/force.go new file mode 100644 index 0000000..f1ce356 --- /dev/null +++ b/cmd/force.go @@ -0,0 +1,149 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "fmt" + "strconv" + + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(forceCmd) + + // Sub-commands + forceCmd.AddCommand(forceSnapshotCmd) + forceCmd.AddCommand(forceBackupCmd) + + // Recon sub-commands + forceCmd.AddCommand(reconCmd) + reconCmd.AddCommand(forceImplicitReconCmd) + reconCmd.AddCommand(forceExplicitReconCmd) +} + +var forceCmd = &cobra.Command{ + Use: "force", + Short: "Force the scheduler to do a snapshot, a backup, or a task reconciliation.", +} + +var forceSnapshotCmd = &cobra.Command{ + Use: "snapshot", + Short: "Force the leading scheduler to perform a Snapshot.", + Long: `Takes a Snapshot of the in memory state of the Apache Aurora cluster and +writes it to the Mesos replicated log. This should NOT be confused with a backup.`, + Run: snapshot, +} + +func snapshot(cmd *cobra.Command, args []string) { + fmt.Println("Forcing scheduler to write snapshot to Mesos replicated log") + err := client.Snapshot() + if err != nil { + log.Fatalf("error: %+v\n", err) + } else { + log.Println("Snapshot started successfully") + } +} + +var forceBackupCmd = &cobra.Command{ + Use: "backup", + Short: "Force the leading scheduler to perform a Backup.", + Long: `Force the Aurora Scheduler to write a backup of the latest snapshot to the filesystem +of the leading scheduler.`, + Run: backup, +} + +func backup(cmd *cobra.Command, args []string) { + fmt.Println("Forcing scheduler to write a Backup of latest Snapshot to file system") + err := client.PerformBackup() + if err != nil { + log.Fatalf("error: %+v", err) + } else { + log.Println("Backup started successfully") + } +} + +var reconCmd = &cobra.Command{ + Use: "recon", + Short: "Force the leading scheduler to perform a reconciliation.", + Long: `Force the Aurora Scheduler to perform a task reconciliation. +Explicit Recon: +Aurora will send a list of non-terminal task IDs and the master responds +with the latest state for each task, if possible. +Implicit Recon: +Aurora will send an empty list of tasks and the master responds with the latest +state for all currently known non-terminal tasks. +`, +} + +var forceExplicitReconCmd = &cobra.Command{ + Use: "explicit [batch_size]", + Short: "Force the leading scheduler to perform an explicit recon.", + Long: `Aurora will send a list of non-terminal task IDs and the master +responds with the latest state for each task, if possible. +`, + Run: explicitRecon, + Args: cobra.MaximumNArgs(1), +} + +func explicitRecon(cmd *cobra.Command, args []string) { + var batchSize *int32 + + log.Println("Forcing scheduler to perform an explicit reconciliation with Mesos") + + switch len(args) { + case 0: + log.Infoln("Using default batch size for explicit recon.") + case 1: + log.Infof("Using %v as batch size for explicit recon.\n", args[0]) + + // Get batch size from args and convert it to the right format + batchInt, err := strconv.Atoi(args[0]) + if err != nil { + log.Fatalf("error: %v", err) + } + + batchInt32 := int32(batchInt) + batchSize = &batchInt32 + default: + log.Fatalln("Provide 0 arguments to use default batch size or one argument to use a custom batch size.") + } + + err := client.ForceExplicitTaskReconciliation(batchSize) + if err != nil { + log.Fatalf("error: %v", err) + } else { + fmt.Println("Explicit reconciliation started successfully") + } +} + +var forceImplicitReconCmd = &cobra.Command{ + Use: "implicit", + Short: "Force the leading scheduler to perform an implicit recon.", + Long: `Forces leading scheduler to ask Mesos Master for a list of the latest state for +all currently known non-terminal tasks being run by Aurora.`, + Run: implicitRecon, +} + +func implicitRecon(cmd *cobra.Command, args []string) { + + log.Println("Forcing scheduler to perform an implicit reconciliation with Mesos") + err := client.ForceImplicitTaskReconciliation() + if err != nil { + log.Fatalf("error: %+v", err) + } else { + fmt.Println("Implicit reconciliation started successfully") + } +} diff --git a/cmd/kill.go b/cmd/kill.go index 971c3a0..98e4401 100644 --- a/cmd/kill.go +++ b/cmd/kill.go @@ -1,49 +1,139 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package cmd import ( - "fmt" - "log" - "os" + "strconv" + "strings" - realis "github.com/paypal/gorealis" - "github.com/paypal/gorealis/gen-go/apache/aurora" + realis "github.com/aurora-scheduler/gorealis/v2" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(killCmd) - killCmd.Flags().StringVarP(&env, "environment", "e", "", "Aurora Environment") - killCmd.Flags().StringVarP(&role, "role", "r", "", "Aurora Role") - killCmd.Flags().StringVarP(&name, "name", "n", "", "Aurora Name") - killCmd.MarkFlagRequired("environment") - killCmd.MarkFlagRequired("role") - killCmd.MarkFlagRequired("name") + + /* Sub-Commands */ + + // Kill Job + killCmd.AddCommand(killJobCmd) + killCmd.AddCommand(killTasksCmd) + + killJobCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + killJobCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + killJobCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + killJobCmd.Flags().BoolVarP(&monitor, "monitor", "m", true, "monitor the result after sending the command") + killJobCmd.MarkFlagRequired("environment") + killJobCmd.MarkFlagRequired("role") + killJobCmd.MarkFlagRequired("name") + + //Set flags for killTask sub-command + killTasksCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + killTasksCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + killTasksCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + killTasksCmd.Flags().StringVarP(instances, "instances", "I", "", "Instances e.g. 1, 2, 5") + killTasksCmd.Flags().BoolVarP(&monitor, "monitor", "m", true, "monitor the result after sending the command") + killTasksCmd.MarkFlagRequired("environment") + killTasksCmd.MarkFlagRequired("role") + killTasksCmd.MarkFlagRequired("name") + killTasksCmd.MarkFlagRequired("instances") } var killCmd = &cobra.Command{ Use: "kill", Short: "Kill an Aurora Job", +} + +var killJobCmd = &cobra.Command{ + Use: "job", + Short: "Kill an Aurora Job", Run: killJob, } +/* +* The killTasks command allows the user to kill a specific task of a job. +* The command also allows the user to kill multiple tasks of the same job. To do so the user needs to pass a list of instance numbers as comma separated values. +* Pass the instance number of the job to be killed after the --instances or -I flag +* Please note that all the instances passed must belong to the same job. +* +* example : australis kill tasks -e "environment" -r "role" -n "job_name" -I "1" +* The above example kills instance number 1. +* +* example 2 : australis kill tasks -e "environment" -r "role" -n "job_name" -I "1, 5, 9" +* The above example kills tasks 1, 5 and 9, which are part of the same job + */ +var killTasksCmd = &cobra.Command{ + Use: "tasks", + Short: "Kill Aurora Tasks", + Run: killTasks, +} + func killJob(cmd *cobra.Command, args []string) { - log.Printf("Killing job [Env:%s Role:%s Name:%s]\n", env, role, name) + log.Infof("Killing job [Env:%s Role:%s Name:%s]\n", *env, *role, *name) job := realis.NewJob(). - Environment(env). - Role(role). - Name(name) - resp, err := client.KillJob(job.JobKey()) + Environment(*env). + Role(*role). + Name(*name) + err := client.KillJob(job.JobKey()) if err != nil { - fmt.Println(err) - os.Exit(1) + log.Fatalln(err) } - - if resp.ResponseCode == aurora.ResponseCode_OK { - if ok, err := monitor.Instances(job.JobKey(), 0, 5, 50); !ok || err != nil { - log.Println("Unable to kill all instances of job") - os.Exit(1) + if monitor { + if ok, err := client.MonitorInstances(job.JobKey(), 0, 5, 50); !ok || err != nil { + log.Fatalln("Unable to kill all instances of job") + } + } +} + +func killTasks(cmd *cobra.Command, args []string) { + log.Infof("Killing task [Env:%s Role:%s Name:%s Instance:%s]\n", *env, *role, *name, *instances) + + //Set jobKey for the tasks to be killed. + task := realis.NewTask(). + Environment(*env). + Role(*role). + Name(*name) + + /* + * In the following block, we convert instance numbers, which were passed as strings, to integer values + * After converting them to integers, we add them to a slice of type int32. + */ + + splitString := strings.Split(*instances, ",") + instanceList := make([]int32, len(splitString)) + + for i := range instanceList { + splitString[i] = strings.TrimSpace(splitString[i]) + instanceNumber, intErr := strconv.Atoi(splitString[i]) + if intErr != nil { + log.Fatalln("Instance passed should be a number. Error: " + intErr.Error()) + return + } else { + instanceList[i] = int32(instanceNumber) + } + } + + //Call the killtasks function, passing the instanceList as the list of instances to be killed. + if _, err := client.KillInstances(task.JobKey(), instanceList...); err != nil { + log.Fatalln(err) + } + + if monitor { + if ok, err := client.MonitorInstances(task.JobKey(), 0, 5, 50); !ok || err != nil { + log.Fatalln("Unable to kill the given task") } } - fmt.Println(resp.String()) } diff --git a/cmd/monitor.go b/cmd/monitor.go new file mode 100644 index 0000000..5d97fba --- /dev/null +++ b/cmd/monitor.go @@ -0,0 +1,72 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "strings" + "time" + + "github.com/aurora-scheduler/australis/internal" + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(monitorCmd) + + monitorCmd.AddCommand(monitorHostCmd.Cmd) + + monitorHostCmd.Cmd.Run = monitorHost + monitorHostCmd.Cmd.Flags().DurationVar(&monitorHostCmd.MonitorInterval, "interval", time.Second*5, "Interval at which to poll scheduler.") + monitorHostCmd.Cmd.Flags().DurationVar(&monitorHostCmd.MonitorTimeout, "timeout", time.Minute*10, "Time after which the monitor will stop polling and throw an error.") + monitorHostCmd.Cmd.Flags().StringSliceVar(&monitorHostCmd.StatusList, "statuses", []string{aurora.MaintenanceMode_DRAINED.String()}, "List of acceptable statuses for a host to be in. (case-insensitive) [NONE, SCHEDULED, DRAINED, DRAINING]") +} + +var monitorCmd = &cobra.Command{ + Use: "monitor", + Short: "Watch for a specific state change", +} + +var monitorHostCmd = internal.MonitorCmdConfig{ + Cmd: &cobra.Command{ + Use: "hosts", + Short: "Watch a host maintenance status until it enters one of the desired statuses.", + Long: `Provide a list of hosts to monitor for desired statuses. Statuses may be passed using the --statuses +flag with a list of comma separated statuses. Statuses include [NONE, SCHEDULED, DRAINED, DRAINING]`, + }, + StatusList: make([]string, 0), +} + +func monitorHost(cmd *cobra.Command, args []string) { + maintenanceModes := make([]aurora.MaintenanceMode, 0) + + for _, status := range monitorHostCmd.StatusList { + mode, err := aurora.MaintenanceModeFromString(strings.ToUpper(status)) + if err != nil { + log.Fatal(err) + } + + maintenanceModes = append(maintenanceModes, mode) + } + + log.Infof("Monitoring for %v at %v intervals", monitorHostCmd.MonitorTimeout, monitorHostCmd.MonitorInterval) + hostResult, err := client.MonitorHostMaintenance(args, maintenanceModes, monitorHostCmd.MonitorInterval, monitorHostCmd.MonitorTimeout) + + internal.MaintenanceMonitorPrint(hostResult, maintenanceModes, toJson) + + if err != nil { + log.Fatal(err) + } +} diff --git a/cmd/pulse.go b/cmd/pulse.go new file mode 100644 index 0000000..64af116 --- /dev/null +++ b/cmd/pulse.go @@ -0,0 +1,47 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(pulseJobUpdateCmd) + + pulseJobUpdateCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + pulseJobUpdateCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + pulseJobUpdateCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + pulseJobUpdateCmd.Flags().StringVar(&updateID, "id", "", "Update ID") +} + +var pulseJobUpdateCmd = &cobra.Command{ + Use: "pulse", + Short: "Pulse a Job update", + Run: pulseJobUpdate, +} + +func pulseJobUpdate(cmd *cobra.Command, args []string) { + _, err := client.PulseJobUpdate( + aurora.JobUpdateKey{ + Job: &aurora.JobKey{Environment: *env, Role: *role, Name: *name}, + ID: updateID, + }) + + if err != nil { + log.Fatal(err) + } +} diff --git a/cmd/restart.go b/cmd/restart.go new file mode 100644 index 0000000..c207ffb --- /dev/null +++ b/cmd/restart.go @@ -0,0 +1,110 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "strconv" + "strings" + + realis "github.com/aurora-scheduler/gorealis/v2" + + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(restartCmd) + + restartCmd.AddCommand(restartJobCmd) + restartJobCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + restartJobCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + restartJobCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + + restartCmd.AddCommand(restartTasksCmd) + restartTasksCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + restartTasksCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + restartTasksCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + restartTasksCmd.Flags().StringVarP(instances, "instances", "I", "", "Instances e.g. 1, 2, 5") + restartTasksCmd.Flags().BoolVarP(&monitor, "monitor", "m", true, "monitor the result after sending the command") + restartTasksCmd.MarkFlagRequired("environment") + restartTasksCmd.MarkFlagRequired("role") + restartTasksCmd.MarkFlagRequired("name") + restartTasksCmd.MarkFlagRequired("instances") +} + +var restartCmd = &cobra.Command{ + Use: "restart", + Short: "Restart an Aurora Job.", +} + +var restartJobCmd = &cobra.Command{ + Use: "job", + Short: "Restart a Job.", + Run: restartJob, +} + +var restartTasksCmd = &cobra.Command{ + Use: "tasks", + Short: "Restart tasks for a Job.", + Run: restartTasks, +} + +func restartJob(cmd *cobra.Command, args []string) { + key := aurora.JobKey{Environment: *env, Role: *role, Name: *name} + if err := client.RestartJob(key); err != nil { + log.Fatal("unable to create Aurora job: ", err) + } +} + +func restartTasks(cmd *cobra.Command, args []string) { + log.Infof("Restarts task [Env:%s Role:%s Name:%s Instance:%s Monitor:%s]\n", *env, *role, *name, *instances, strconv.FormatBool(monitor)) + + //Set jobKey for the tasks to be killed. + task := realis.NewTask(). + Environment(*env). + Role(*role). + Name(*name) + + /* + * In the following block, we convert instance numbers, which were passed as strings, to integer values + * After converting them to integers, we add them to a slice of type int32. + */ + + splitString := strings.Split(*instances, ",") + instanceList := make([]int32, len(splitString)) + + for i := range instanceList { + splitString[i] = strings.TrimSpace(splitString[i]) + var instanceNumber int + var err error + if instanceNumber, err = strconv.Atoi(splitString[i]); err != nil { + log.Fatalln("Instance passed should be a number. Error: " + err.Error()) + return + } + instanceList[i] = int32(instanceNumber) + } + + //Call the RestartInstances function, passing the instanceList as the list of instances to be restarted. + if err := client.RestartInstances(task.JobKey(), instanceList...); err != nil { + log.Fatalln(err) + } + + if monitor { + if ok, err := client.MonitorInstances(task.JobKey(), int32(len(instanceList)), 5, 50); !ok || err != nil { + log.Fatalln("Monitor failed to monitor the given task after restart. Error: " + err.Error()) + } + } + +} diff --git a/cmd/resume.go b/cmd/resume.go new file mode 100644 index 0000000..0d3a7e2 --- /dev/null +++ b/cmd/resume.go @@ -0,0 +1,49 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(resumeJobUpdateCmd) + + resumeJobUpdateCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + resumeJobUpdateCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + resumeJobUpdateCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + resumeJobUpdateCmd.Flags().StringVar(&updateID, "id", "", "Update ID") + resumeJobUpdateCmd.Flags().StringVar(message, "message", "", "Message to store along resume.") +} + +var resumeJobUpdateCmd = &cobra.Command{ + Use: "resume", + Short: "Resume a Job update", + Run: resumeJobUpdate, +} + +func resumeJobUpdate(cmd *cobra.Command, args []string) { + err := client.ResumeJobUpdate( + aurora.JobUpdateKey{ + Job: &aurora.JobKey{Environment: *env, Role: *role, Name: *name}, + ID: updateID, + }, + *message) + + if err != nil { + log.Fatal(err) + } +} diff --git a/cmd/rollback.go b/cmd/rollback.go new file mode 100644 index 0000000..3db2f5b --- /dev/null +++ b/cmd/rollback.go @@ -0,0 +1,65 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "fmt" + + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(rollbackCmd) + + rollbackCmd.AddCommand(rollbackUpdateCmd) + rollbackUpdateCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + rollbackUpdateCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + rollbackUpdateCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + rollbackUpdateCmd.Flags().StringVar(&updateID, "id", "", "Update ID") + rollbackUpdateCmd.Flags().StringVar(message, "message", "", "Message to store alongside resume event") + rollbackUpdateCmd.MarkFlagRequired("environment") + rollbackUpdateCmd.MarkFlagRequired("role") + rollbackUpdateCmd.MarkFlagRequired("name") + rollbackUpdateCmd.MarkFlagRequired("id") +} + +var rollbackCmd = &cobra.Command{ + Use: "rollback", + Short: "Rollback an operation such as an Update", +} + +var rollbackUpdateCmd = &cobra.Command{ + Use: "update", + Short: "Rollback an update", + Run: rollbackUpdate, +} + +func rollbackUpdate(cmd *cobra.Command, args []string) { + var updateMessage string + if message != nil { + updateMessage = *message + } + err := client.RollbackJobUpdate(aurora.JobUpdateKey{ + Job: &aurora.JobKey{Environment: *env, Role: *role, Name: *name}, + ID: updateID, + }, updateMessage) + + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Rollback update for update ID %v sent successfully\n", updateID) +} diff --git a/cmd/root.go b/cmd/root.go index 21c1d44..722358b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,14 +1,80 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package cmd import ( - "fmt" - "os" + "strings" "time" - "github.com/paypal/gorealis" + "github.com/aurora-scheduler/australis/internal" + "github.com/spf13/viper" + + realis "github.com/aurora-scheduler/gorealis/v2" "github.com/spf13/cobra" + + "github.com/sirupsen/logrus" ) +var username, password, zkAddr, schedAddr string +var env, role, name = new(string), new(string), new(string) +var dedicated string +var ram, disk, gpu, port int64 +var cpu float64 +var client *realis.Client +var skipCertVerification bool +var caCertsPath string +var clientKey, clientCert string +var configFile string +var toJson bool +var fromJson bool +var fromJsonFile string +var logLevel string +var duration time.Duration +var percent float64 +var count int64 +var filename string +var message = new(string) +var updateID string +var monitor bool +var timeout time.Duration +var log = logrus.New() +var taskStatus = new(string) +var instances = new(string) + +const australisVer = "v1.0.5" + +var forceDrainTimeout time.Duration + +func init() { + + rootCmd.SetVersionTemplate(`{{printf "%s\n" .Version}}`) + + rootCmd.PersistentFlags().StringVarP(&zkAddr, "zookeeper", "z", "", "Zookeeper node(s) where Aurora stores information. (comma separated list)") + rootCmd.PersistentFlags().StringVarP(&username, "username", "u", "", "Username to use for API authentication") + rootCmd.PersistentFlags().StringVarP(&password, "password", "p", "", "Password to use for API authentication") + rootCmd.PersistentFlags().StringVarP(&schedAddr, "scheduler_addr", "s", "", "Aurora Scheduler's address.") + rootCmd.PersistentFlags().StringVarP(&clientKey, "clientKey", "k", "", "Client key to use to connect to Aurora.") + rootCmd.PersistentFlags().StringVarP(&clientCert, "clientCert", "c", "", "Client certificate to use to connect to Aurora.") + rootCmd.PersistentFlags().StringVarP(&caCertsPath, "caCertsPath", "a", "", "Path where CA certificates can be found.") + rootCmd.PersistentFlags().BoolVarP(&skipCertVerification, "skipCertVerification", "i", false, "Skip CA certificate hostname verification.") + rootCmd.PersistentFlags().StringVar(&configFile, "config", "/etc/aurora/australis.yml", "Config file to use.") + rootCmd.PersistentFlags().BoolVar(&toJson, "toJSON", false, "Print output in JSON format.") + rootCmd.PersistentFlags().StringVarP(&logLevel, "logLevel", "l", "info", "Set logging level ["+internal.GetLoggingLevels()+"].") + rootCmd.PersistentFlags().DurationVarP(&timeout, "timeout", "t", 20*time.Second, "Gorealis timeout.") +} + var rootCmd = &cobra.Command{ Use: "australis", Short: "australis is a client for Apache Aurora", @@ -18,74 +84,101 @@ var rootCmd = &cobra.Command{ // Make all children close the client by default upon terminating client.Close() }, -} - -var username, password, zkAddr, schedAddr string -var env, role, name string -var client realis.Realis -var monitor *realis.Monitor -var insecureSkipVerify bool -var caCertsPath string -var clientKey, clientCert string - -var monitorInterval, monitorTimeout int - -func init() { - rootCmd.PersistentFlags().StringVarP(&zkAddr, "zookeeper", "z", "", "Zookeeper node(s) where Aurora stores information.") - rootCmd.PersistentFlags().StringVarP(&username, "username", "u", "", "Username to use for API authentication") - rootCmd.PersistentFlags().StringVarP(&password, "password", "p", "", "Password to use for API authentication") - rootCmd.PersistentFlags().StringVarP(&schedAddr, "scheduler_addr", "s", "", "Aurora Scheduler's address.") - rootCmd.PersistentFlags().StringVarP(&clientKey, "clientKey", "k", "", "Client key to use to connect to Aurora.") - rootCmd.PersistentFlags().StringVarP(&clientCert, "clientCert", "c", "", "Client certificate to use to connect to Aurora.") - rootCmd.PersistentFlags().StringVarP(&caCertsPath, "caCertsPath", "a", "", "CA certificates path to use.") - rootCmd.PersistentFlags().BoolVarP(&insecureSkipVerify, "insecureSkipVerify", "i", false, "Skip verification.") + Version: australisVer, } func Execute() { - rootCmd.Execute() + if err := rootCmd.Execute(); err != nil { + log.Fatal(err) + } +} + +// TODO(rdelvalle): Move more from connect into this function +func setConfig(cmd *cobra.Command, args []string) { + lvl, err := logrus.ParseLevel(logLevel) + + if err != nil { + log.Fatalf("Log level %v is not valid", logLevel) + } + + log.SetLevel(lvl) + internal.Logger(log) } func connect(cmd *cobra.Command, args []string) { - var err error + setConfig(cmd, args) + + zkAddrSlice := strings.Split(zkAddr, ",") + + viper.SetConfigFile(configFile) + err = viper.ReadInConfig() + if err == nil { + // Best effort load configuration. Will only set config values when flags have not set them already. + if viper.IsSet("zk") && len(zkAddrSlice) == 1 && zkAddrSlice[0] == "" { + zkAddrSlice = viper.GetStringSlice("zk") + } + + if viper.IsSet("username") && username == "" { + username = viper.GetString("username") + } + + if viper.IsSet("password") && password == "" { + password = viper.GetString("password") + } + + if viper.IsSet("clientKey") && clientKey == "" { + clientKey = viper.GetString("clientKey") + } + + if viper.IsSet("clientCert") && clientCert == "" { + clientCert = viper.GetString("clientCert") + } + + if viper.IsSet("caCertsPath") && caCertsPath == "" { + caCertsPath = viper.GetString("caCertsPath") + } + + if viper.IsSet("skipCertVerification") && !skipCertVerification { + skipCertVerification = viper.GetBool("skipCertVerification") + } + } + realisOptions := []realis.ClientOption{realis.BasicAuth(username, password), realis.ThriftJSON(), - realis.TimeoutMS(20000), + realis.Timeout(timeout), realis.BackOff(realis.Backoff{ Steps: 2, Duration: 10 * time.Second, Factor: 2.0, Jitter: 0.1, - })} + }), + realis.SetLogger(log)} // Prefer zookeeper if both ways of connecting are provided - if zkAddr != "" { - + if len(zkAddrSlice) > 0 && zkAddrSlice[0] != "" { // Configure Zookeeper to connect - zkOptions := []realis.ZKOpt{ realis.ZKEndpoints(zkAddr), realis.ZKPath("/aurora/scheduler")} - - if clientKey != "" || clientCert != "" || caCertsPath != "" { - zkOptions = append(zkOptions, realis.ZKAuroraPortOverride(8081), realis.ZKAuroraSchemeOverride("https")) - - realisOptions = append(realisOptions, realis.Certspath(caCertsPath), realis.ClientCerts(clientKey, clientCert)) - } - + zkOptions := []realis.ZKOpt{realis.ZKEndpoints(zkAddrSlice...), realis.ZKPath("/aurora/scheduler")} realisOptions = append(realisOptions, realis.ZookeeperOptions(zkOptions...)) } else if schedAddr != "" { realisOptions = append(realisOptions, realis.SchedulerUrl(schedAddr)) } else { - fmt.Println("Zookeeper address or Scheduler URL must be provided.") - os.Exit(1) + log.Fatalln("Zookeeper address or Scheduler URL must be provided.") + } + + // Client certificate configuration if available + if clientKey != "" || clientCert != "" || caCertsPath != "" { + realisOptions = append(realisOptions, + realis.CertsPath(caCertsPath), + realis.ClientCerts(clientKey, clientCert), + realis.InsecureSkipVerify(skipCertVerification)) } // Connect to Aurora Scheduler and create a client object - client, err = realis.NewRealisClient(realisOptions...) + client, err = realis.NewClient(realisOptions...) if err != nil { - fmt.Println(err) - os.Exit(1) + log.Fatal(err) } - monitor = &realis.Monitor{Client: client} - } diff --git a/cmd/schedule.go b/cmd/schedule.go new file mode 100644 index 0000000..c4e13d2 --- /dev/null +++ b/cmd/schedule.go @@ -0,0 +1,52 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "github.com/aurora-scheduler/australis/internal" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(scheduleCmd) + +} + +var scheduleCmd = &cobra.Command{ + Use: "schedule", + Short: "Schedule a cron job on Aurora scheduler", + Run: scheduleCron, + Args: cobra.ExactArgs(1), +} + +func scheduleCron(cmd *cobra.Command, args []string) { + job, err := internal.UnmarshalJob(args[0]) + if err != nil { + log.Fatalln(err) + } + + if err := job.ValidateCron(); err != nil { + log.Fatal(err) + } + + auroraJob, err := job.ToRealis() + if err != nil { + log.Fatalln(err) + } + + if err := client.ScheduleCronJob(auroraJob); err != nil { + log.Fatal("unable to schedule job: ", err) + } +} diff --git a/cmd/set.go b/cmd/set.go new file mode 100644 index 0000000..bdfa45f --- /dev/null +++ b/cmd/set.go @@ -0,0 +1,94 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "fmt" + "strconv" + "strings" + + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(setCmd) + + // Set Sub-commands + setCmd.AddCommand(setQuotaCmd) +} + +var setCmd = &cobra.Command{ + Use: "set", + Short: "Set a value in the Aurora Scheduler.", +} + +var setQuotaCmd = &cobra.Command{ + Use: "quota cpu: ram: disk:", + Short: "Set Quota resources for a role.", + Long: `Quotas can be set for roles in Aurora. Using this command we can set the resources reserved a role.`, + Run: setQuota, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 4 { + return fmt.Errorf("role, cpu, ram, and disk resources must be provided") + } + + *role = args[0] + + for i := 1; i < len(args); i++ { + resourcePair := strings.Split(args[i], ":") + + if len(resourcePair) != 2 { + return fmt.Errorf("all resources must be provided in : format") + } + + var err error + switch resourcePair[0] { + + case "cpu": + cpu, err = strconv.ParseFloat(resourcePair[1], 64) + if err != nil { + return errors.Wrap(err, "unable to convert CPU value provided to a floating point number") + } + case "ram": + ram, err = strconv.ParseInt(resourcePair[1], 10, 64) + if err != nil { + return errors.Wrap(err, "unable to convert RAM value provided to a integer number") + } + + case "disk": + disk, err = strconv.ParseInt(resourcePair[1], 10, 64) + if err != nil { + return errors.Wrap(err, "unable to convert DISK value provided to a integer number") + } + default: + return fmt.Errorf("unknown resource value provided, only cpu, ram, and disk are supported") + } + } + + return nil + }, +} + +func setQuota(cmd *cobra.Command, args []string) { + log.Println("Setting Quota resources for role.") + log.Println(args) + + err := client.SetQuota(*role, &cpu, &ram, &disk) + + if err != nil { + log.Fatal(err) + } +} diff --git a/cmd/simulate.go b/cmd/simulate.go new file mode 100644 index 0000000..a292693 --- /dev/null +++ b/cmd/simulate.go @@ -0,0 +1,61 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "fmt" + + "github.com/aurora-scheduler/australis/internal" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(simulateCmd) + + simulateCmd.AddCommand(fitCmd) +} + +var simulateCmd = &cobra.Command{ + Use: "simulate", + Short: "Simulate some work based on the current cluster condition, and return the output", +} + +var fitCmd = &cobra.Command{ + Use: "fit", + Short: "Compute how many tasks can we fit to a cluster", + Run: fit, + Args: cobra.RangeArgs(1, 2), +} + +func fit(cmd *cobra.Command, args []string) { + log.Infof("Compute how many tasks can be fit in the remaining cluster capacity") + + taskConfig, err := internal.UnmarshalTaskConfig(args[0]) + if err != nil { + log.Fatalln(err) + } + + offers, err := client.Offers() + if err != nil { + log.Fatal("error: %+v", err) + } + + numTasks, err := client.FitTasks(taskConfig, offers) + if err != nil { + log.Fatal("error: %+v", err) + } + + fmt.Println(numTasks) +} diff --git a/cmd/start.go b/cmd/start.go index 96c9511..39cc7dd 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -1,66 +1,297 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package cmd import ( - "fmt" + "encoding/json" + "errors" + "io/ioutil" "os" + "time" - "github.com/paypal/gorealis/gen-go/apache/aurora" + "github.com/aurora-scheduler/australis/internal" + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" "github.com/spf13/cobra" ) +const countFlag = "count" +const percentageFlag = "percentage" +const jsonFlag = "json" +const jsonFileFlag = "json-file" + func init() { rootCmd.AddCommand(startCmd) - // Sub-commands - startCmd.AddCommand(startMaintCmd) + startCmd.AddCommand(startDrainCmd.Cmd) + startDrainCmd.Cmd.Run = drain - startMaintCmd.Flags().IntVar(&monitorInterval,"interval", 5, "Interval at which to poll scheduler.") - startMaintCmd.Flags().IntVar(&monitorTimeout,"timeout", 50, "Time after which the monitor will stop polling and throw an error.") + // Maintenance specific flags + startDrainCmd.Cmd.Flags().DurationVar(&startDrainCmd.MonitorInterval, "interval", time.Second*5, "Interval at which to poll scheduler.") + startDrainCmd.Cmd.Flags().DurationVar(&startDrainCmd.MonitorTimeout, "timeout", time.Minute*10, "Time after which the monitor will stop polling and throw an error.") + startDrainCmd.Cmd.Flags().StringVar(&fromJsonFile, jsonFileFlag, "", "JSON file to read list of agents from.") + startDrainCmd.Cmd.Flags().BoolVar(&fromJson, jsonFlag, false, "Read JSON list of agents from the STDIN.") + /* SLA Aware commands */ + startCmd.AddCommand(startSLADrainCmd.Cmd) + startSLADrainCmd.Cmd.Run = slaDrain + + // SLA Maintenance specific flags + startSLADrainCmd.Cmd.Flags().Int64Var(&count, countFlag, 5, "Instances count that should be running to meet SLA.") + startSLADrainCmd.Cmd.Flags().Float64Var(&percent, percentageFlag, 80.0, "Percentage of instances that should be running to meet SLA.") + startSLADrainCmd.Cmd.Flags().DurationVar(&duration, "duration", time.Minute*1, "Minimum time duration a task needs to be `RUNNING` to be treated as active.") + startSLADrainCmd.Cmd.Flags().DurationVar(&forceDrainTimeout, "sla-limit", time.Minute*60, "Time limit after which SLA-Aware drain sheds SLA Awareness.") + startSLADrainCmd.Cmd.Flags().DurationVar(&startSLADrainCmd.MonitorInterval, "interval", time.Second*10, "Interval at which to poll scheduler.") + startSLADrainCmd.Cmd.Flags().DurationVar(&startSLADrainCmd.MonitorTimeout, "timeout", time.Minute*20, "Time after which the monitor will stop polling and throw an error.") + startSLADrainCmd.Cmd.Flags().StringVar(&fromJsonFile, jsonFileFlag, "", "JSON file to read list of agents from.") + startSLADrainCmd.Cmd.Flags().BoolVar(&fromJson, jsonFlag, false, "Read JSON list of agents from the STDIN.") + + startCmd.AddCommand(startMaintenanceCmd.Cmd) + startMaintenanceCmd.Cmd.Run = maintenance + + // SLA Maintenance specific flags + startMaintenanceCmd.Cmd.Flags().DurationVar(&startMaintenanceCmd.MonitorInterval, "interval", time.Second*5, "Interval at which to poll scheduler.") + startMaintenanceCmd.Cmd.Flags().DurationVar(&startMaintenanceCmd.MonitorTimeout, "timeout", time.Minute*10, "Time after which the monitor will stop polling and throw an error.") + startMaintenanceCmd.Cmd.Flags().StringVar(&fromJsonFile, jsonFileFlag, "", "JSON file to read list of agents from.") + startMaintenanceCmd.Cmd.Flags().BoolVar(&fromJson, jsonFlag, false, "Read JSON list of agents from the STDIN.") + + // Start update command + startCmd.AddCommand(startUpdateCmd.Cmd) + startUpdateCmd.Cmd.Run = update + startUpdateCmd.Cmd.Flags().DurationVar(&startUpdateCmd.MonitorInterval, "interval", time.Second*5, "Interval at which to poll scheduler.") + startUpdateCmd.Cmd.Flags().DurationVar(&startUpdateCmd.MonitorTimeout, "timeout", time.Minute*10, "Time after which the monitor will stop polling and throw an error.") } var startCmd = &cobra.Command{ Use: "start", - Short: "Start a service or maintenance on a host (DRAIN).", + Short: "Start a service, maintenance on a host (DRAIN), a snapshot, an update, or a backup.", } -var startMaintCmd = &cobra.Command{ - Use: "drain [space separated host list]", - Short: "Place a list of space separated Mesos Agents into maintenance mode.", - Long: `Adds a Mesos Agent to Aurora's Drain list. Agents in this list +var startDrainCmd = internal.MonitorCmdConfig{ + Cmd: &cobra.Command{ + Use: "drain [space separated host list or use JSON flags]", + Short: "Place a list of space separated Mesos Agents into draining mode.", + Long: `Adds a Mesos Agent to Aurora's Drain list. Agents in this list are not allowed to schedule new tasks and any tasks already running on this Agent are killed and rescheduled in an Agent that is not in maintenance mode. Command expects a space separated list of hosts to place into maintenance mode.`, - Args: cobra.MinimumNArgs(1), - Run: drain, + Args: argsValidateJSONFlags, + }, +} + +var startSLADrainCmd = internal.MonitorCmdConfig{ + Cmd: &cobra.Command{ + Use: "sla-drain [space separated host list or use JSON flags]", + Short: "Place a list of space separated Mesos Agents into maintenance mode using SLA aware strategies.", + Long: `Adds a Mesos Agent to Aurora's Drain list. Agents in this list +are not allowed to schedule new tasks and any tasks already running on this Agent +are killed and rescheduled in an Agent that is not in maintenance mode. Command +expects a space separated list of hosts to place into maintenance mode. +If the --count argument is passed, tasks will be drained using the count SLA policy as a fallback +when a Job does not have a defined SLA policy. +If the --percentage argument is passed, tasks will be drained using the percentage SLA policy as a fallback +when a Job does not have a defined SLA policy.`, + Args: argsValidateJSONFlags, + }, +} + +var startMaintenanceCmd = internal.MonitorCmdConfig{ + Cmd: &cobra.Command{ + Use: "maintenance [space separated host list or use JSON flags]", + Short: "Place a list of space separated Mesos Agents into maintenance mode.", + Long: `Places Mesos Agent into Maintenance mode. Agents in this list +are de-prioritized for scheduling a task. Command +expects a space separated list of hosts to place into maintenance mode.`, + Args: argsValidateJSONFlags, + }, +} + +var startUpdateCmd = internal.MonitorCmdConfig{ + Cmd: &cobra.Command{ + Use: "update [update config]", + Short: "Start an update on an Aurora long running service.", + Long: `Starts the update process on an Aurora long running service. If no such service exists, the update mechanism +will act as a deployment, creating all new instances based on the requirements in the update configuration.`, + Args: cobra.ExactArgs(1), + }, +} + +func argsValidateJSONFlags(cmd *cobra.Command, args []string) error { + if cmd.Flags().Changed(jsonFlag) && cmd.Flags().Changed(jsonFileFlag) { + return errors.New("only json file or json stdin must be set") + } + // These two flags are mutually exclusive + if cmd.Flags().Changed(jsonFlag) != cmd.Flags().Changed(jsonFileFlag) { + return nil + } + + if len(args) < 1 { + return errors.New("at least one host must be specified") + } + return nil +} + +func hostList(cmd *cobra.Command, args []string) []string { + var hosts []string + if cmd.Flags().Changed(jsonFlag) { + err := json.NewDecoder(os.Stdin).Decode(&hosts) + if err != nil { + log.Fatal(err) + } + } else if cmd.Flags().Changed(jsonFileFlag) { + data, err := ioutil.ReadFile(fromJsonFile) + if err != nil { + log.Fatal(err) + } + + err = json.Unmarshal(data, &hosts) + if err != nil { + log.Fatal(err) + } + } else { + hosts = args + } + + return hosts } func drain(cmd *cobra.Command, args []string) { - fmt.Println("Setting hosts to DRAINING") - fmt.Println(args) - _, result, err := client.DrainHosts(args...) + hosts := hostList(cmd, args) + + log.Infoln("Setting hosts to DRAINING") + log.Infoln(hosts) + result, err := client.DrainHosts(hosts...) if err != nil { - fmt.Printf("error: %+v\n", err.Error()) - os.Exit(1) + log.Fatalf("error: %+v", err) } + log.Debugln(result) + + log.Infof("Monitoring for %v at %v intervals", monitorHostCmd.MonitorTimeout, monitorHostCmd.MonitorInterval) + // Monitor change to DRAINING and DRAINED mode + hostResult, err := client.MonitorHostMaintenance( + hosts, + []aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED}, + startDrainCmd.MonitorInterval, + startDrainCmd.MonitorTimeout) + + internal.MaintenanceMonitorPrint(hostResult, []aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED}, toJson) + + if err != nil { + log.Fatalln(err) + } +} + +func slaDrainHosts(policy *aurora.SlaPolicy, interval, timeout time.Duration, hosts ...string) { + result, err := client.SLADrainHosts(policy, int64(forceDrainTimeout.Seconds()), hosts...) + if err != nil { + log.Fatalf("error: %+v", err) + } + + log.Debugln(result) + + log.Infof("Monitoring for %v at %v intervals", timeout, interval) + // Monitor change to DRAINING and DRAINED mode + hostResult, err := client.MonitorHostMaintenance( + hosts, + []aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED}, + interval, + timeout) + + internal.MaintenanceMonitorPrint(hostResult, []aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED}, toJson) + + if err != nil { + log.Fatalf("error: %+v", err) + } +} +func slaDrain(cmd *cobra.Command, args []string) { + hosts := hostList(cmd, args) + + // This check makes sure only a single flag is set. + // If they're both set or both not set, the statement will evaluate to true. + if cmd.Flags().Changed(percentageFlag) == cmd.Flags().Changed(countFlag) { + log.Fatal("Either percentage or count must be set exclusively.") + } + + policy := &aurora.SlaPolicy{} + + if cmd.Flags().Changed(percentageFlag) { + log.Infoln("Setting hosts to DRAINING with the Percentage SLA policy.") + policy.PercentageSlaPolicy = &aurora.PercentageSlaPolicy{ + Percentage: percent, + DurationSecs: int64(duration.Seconds()), + } + } + + if cmd.Flags().Changed(countFlag) { + log.Infoln("Setting hosts to DRAINING with the Count SLA policy.") + policy.CountSlaPolicy = &aurora.CountSlaPolicy{Count: count, DurationSecs: int64(duration.Seconds())} + } + + log.Infoln("Hosts affected: ", args) + slaDrainHosts(policy, startDrainCmd.MonitorInterval, startDrainCmd.MonitorTimeout, hosts...) +} + +func maintenance(cmd *cobra.Command, args []string) { + hosts := hostList(cmd, args) + + log.Infoln("Setting hosts to Maintenance mode") + log.Infoln(hosts) + result, err := client.StartMaintenance(hosts...) + if err != nil { + log.Fatalf("error: %+v", err) + } + + log.Debugln(result) + + log.Infof("Monitoring for %v at %v intervals", monitorHostCmd.MonitorTimeout, monitorHostCmd.MonitorInterval) + // Monitor change to DRAINING and DRAINED mode - hostResult, err := monitor.HostMaintenance( - args, - []aurora.MaintenanceMode{aurora.MaintenanceMode_DRAINED}, - monitorInterval, - monitorTimeout) - if err != nil { - for host, ok := range hostResult { - if !ok { - fmt.Printf("Host %s did not transtion into desired mode(s)\n", host) - } - } + hostResult, err := client.MonitorHostMaintenance( + hosts, + []aurora.MaintenanceMode{aurora.MaintenanceMode_SCHEDULED}, + startMaintenanceCmd.MonitorInterval, + startMaintenanceCmd.MonitorTimeout) - fmt.Printf("error: %+v\n", err.Error()) - return + internal.MaintenanceMonitorPrint(hostResult, []aurora.MaintenanceMode{aurora.MaintenanceMode_SCHEDULED}, toJson) + + if err != nil { + log.Fatalf("error: %+v", err) + } +} + +func update(cmd *cobra.Command, args []string) { + updateJob, err := internal.UnmarshalUpdate(args[0]) + if err != nil { + log.Fatal(err) + } + + update, err := updateJob.ToRealis() + if err != nil { + log.Fatal(err) + } + + result, err := client.StartJobUpdate(update, "") + if err != nil { + log.Fatalf("Update failed to start %v", err) + } + + if ok, monitorErr := client.MonitorJobUpdate(*result.GetKey(), + startUpdateCmd.MonitorInterval, + startUpdateCmd.MonitorTimeout); !ok || monitorErr != nil { + log.Fatal("update did not ROLL FORWARD before monitor timed out") } - fmt.Println(result.String()) } diff --git a/cmd/stop.go b/cmd/stop.go index fde50da..078a600 100644 --- a/cmd/stop.go +++ b/cmd/stop.go @@ -1,10 +1,24 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package cmd import ( - "fmt" - "os" + "time" - "github.com/paypal/gorealis/gen-go/apache/aurora" + "github.com/aurora-scheduler/australis/internal" + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" "github.com/spf13/cobra" ) @@ -12,7 +26,18 @@ func init() { rootCmd.AddCommand(stopCmd) // Stop subcommands - stopCmd.AddCommand(stopMaintCmd) + stopCmd.AddCommand(stopMaintCmd.Cmd) + stopMaintCmd.Cmd.Run = endMaintenance + stopMaintCmd.Cmd.Flags().DurationVar(&stopMaintCmd.MonitorInterval, "interval", time.Second*5, "Interval at which to poll scheduler.") + stopMaintCmd.Cmd.Flags().DurationVar(&stopMaintCmd.MonitorTimeout, "timeout", time.Minute*1, "Time after which the monitor will stop polling and throw an error.") + + // Stop update + + stopCmd.AddCommand(stopUpdateCmd) + stopUpdateCmd.Flags().StringVarP(env, "environment", "e", "", "Aurora Environment") + stopUpdateCmd.Flags().StringVarP(role, "role", "r", "", "Aurora Role") + stopUpdateCmd.Flags().StringVarP(name, "name", "n", "", "Aurora Name") + } var stopCmd = &cobra.Command{ @@ -20,38 +45,60 @@ var stopCmd = &cobra.Command{ Short: "Stop a service or maintenance on a host (DRAIN).", } -var stopMaintCmd = &cobra.Command{ - Use: "drain [space separated host list]", - Short: "Stop maintenance on a host (move to NONE).", - Long: `Transition a list of hosts currently in a maintenance status out of it.`, - Run: endMaintenance, +var stopMaintCmd = internal.MonitorCmdConfig{ + Cmd: &cobra.Command{ + Use: "drain [space separated host list]", + Short: "Stop maintenance on a host (move to NONE).", + Long: `Transition a list of hosts currently in a maintenance status out of it.`, + }, +} + +var stopUpdateCmd = &cobra.Command{ + Use: "update [update ID]", + Short: "Stop update", + Long: `To be written.`, + Run: stopUpdate, } func endMaintenance(cmd *cobra.Command, args []string) { - fmt.Println("Setting hosts to NONE maintenance status.") - fmt.Println(args) - _, result, err := client.EndMaintenance(args...) + log.Println("Setting hosts to NONE maintenance status.") + log.Println(args) + result, err := client.EndMaintenance(args...) if err != nil { - fmt.Printf("error: %+v\n", err.Error()) - os.Exit(1) + log.Fatalf("error: %+v", err) } + log.Debugln(result) + // Monitor change to NONE mode - hostResult, err := monitor.HostMaintenance( + hostResult, err := client.MonitorHostMaintenance( args, []aurora.MaintenanceMode{aurora.MaintenanceMode_NONE}, - 5, - 10) - if err != nil { - for host, ok := range hostResult { - if !ok { - fmt.Printf("Host %s did not transtion into desired mode(s)\n", host) - } - } + stopMaintCmd.MonitorInterval, + stopMaintCmd.MonitorTimeout) - fmt.Printf("error: %+v\n", err.Error()) - return + internal.MaintenanceMonitorPrint(hostResult, []aurora.MaintenanceMode{aurora.MaintenanceMode_NONE}, toJson) + + if err != nil { + log.Fatalf("error: %+v", err) + } +} + +func stopUpdate(cmd *cobra.Command, args []string) { + + if len(args) != 1 { + log.Fatalln("Only a single update ID must be provided.") } - fmt.Print(result.String()) + log.Infof("Stopping (aborting) update [%s/%s/%s] %s\n", *env, *role, *name, args[0]) + + err := client.AbortJobUpdate(aurora.JobUpdateKey{ + Job: &aurora.JobKey{Environment: *env, Role: *role, Name: *name}, + ID: args[0], + }, + "") + + if err != nil { + log.Fatalln(err) + } } diff --git a/deb-packaging/Dockerfile b/deb-packaging/Dockerfile new file mode 100644 index 0000000..6088aa8 --- /dev/null +++ b/deb-packaging/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:16.04 + +RUN apt-get update -y && \ + apt-get install -y build-essential devscripts dh-exec dh-make git lintian wget && \ + wget https://dl.google.com/go/go1.15.2.linux-amd64.tar.gz -O /tmp/go.tar.gz + +RUN tar -C /usr/local -xzf /tmp/go.tar.gz + +ENV PATH=$PATH:/usr/local/go/bin + +COPY ./entrypoint.sh / + +ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/deb-packaging/build_deb.sh b/deb-packaging/build_deb.sh new file mode 100644 index 0000000..958eaa8 --- /dev/null +++ b/deb-packaging/build_deb.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +docker build . -t australis_deb_builder + +docker run --rm -v $HOME/go/pkg/mod:/go/pkg/mod -v $(pwd)/..:/australis australis_deb_builder diff --git a/deb-packaging/entrypoint.sh b/deb-packaging/entrypoint.sh new file mode 100755 index 0000000..601733e --- /dev/null +++ b/deb-packaging/entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Build debian package +cd /australis +debuild -d -us -uc -b + +# Move resulting packages to the dist folder +mkdir -p /australis/dist +mv /australis_*_amd64* /australis/dist diff --git a/debian/australis.install b/debian/australis.install new file mode 100755 index 0000000..5d7fc37 --- /dev/null +++ b/debian/australis.install @@ -0,0 +1,5 @@ +#!/usr/bin/dh-exec + +build/australis.bash => usr/share/bash-completion/completions/australis +build/australis usr/bin +debian/etc/aurora/australis.yml etc/aurora diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..07a8161 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,110 @@ +australis (1.0.5) stable; urgency=medium + + * kill tasks + * fetch all aurora & mesos master nodes + + -- Nhat Tan Le Wed, 31 Aug 2022 15:03:24 -0700 + +australis (1.0.4) stable; urgency=medium + + * fetch free capacity + * simulate task fitting - compute how many tasks can be fit in the remaining capacity + + -- Nhat Tan Le Tue, 2 Aug 2022 16:19:24 -0700 + +australis (1.0.3) stable; urgency=medium + + * Update CI to compile on PRs + * Add tier and production in task config + * Add fetch quota command + * Add priority into job config + + -- Nhat Tan Le Wed, 20 Oct 2021 14:24:10 -0700 + +australis (1.0.2) stable; urgency=medium + + * Fixing broken Thrift dependency by bumping up backported version to thrift v0.13.2 + + -- Renan Del Valle Mon, 11 Jan 2021 17:57:10 -0800 + +australis (1.0.1) stable; urgency=medium + + * Added flag -m and --monitor that can be set in order to monitor a job creation or a job kill. By default monitor is set to true. + + -- Renan Del Valle Wed, 30 Sep 2020 16:46:56 -0700 + +australis (1.0.0) stable; urgency=medium + + * First stable release. + + -- Renan Del Valle Wed, 30 Sep 2020 15:39:29 -0700 + +australis (0.22.0) unstable; urgency=medium + + * Added support for starting job updates. + * Added support for setting SlaAwareness for updates. + * Added upport for scheduling cron jobs. + + -- Renan Del Valle Thu, 07 May 2020 12:00:00 -0700 + +australis (0.1.1) unstable; urgency=medium + + * Removed support for building with dep + * Upgraded depdencies to their latest versions. + * gorealis v2 now lives in the aurora-scheduler organization and dependencies have been updated to reflect that. + + -- Renan DelValle Mon, 19 Feb 2020 12:00:00 -0700 + +australis (0.1.0) unstable; urgency=medium + + * Adding support for drain sub-command to take in JSON list from stdin or from a specified file. + * Added flags json-file and json to drain, maintenance, and sla-drain. + + -- Renan DelValle Mon, 10 Feb 2020 12:00:00 -0700 + +australis (0.0.9) unstable; urgency=medium + + * added ability to create jobs which contain an executorless docker container. + * sla-aware draining sub-command has been simplified. instead of having a count/percentage + subcommand, it now has a flag for each of these options. the count and percentage flag are + mutually exclusive, and one of them has to be set. + + -- Renan DelValle Wed, 29 Jan 2020 15:10:00 -0700 + +australis (0.0.8) unstable; urgency=medium + + * Upgraded default timeouts and durations for sla-aware draining. + * Added ability for controlling when an SLA-Aware drain sheds + SLA awareness for SLA-aware drain policies + * Added monitor verb along with hosts noun. + * Fixed bug with monitor not using the correct default values + for sla-aware drain policies. + + -- Renan DelValle Fri, 25 Mar 2019 15:10:00 -0700 + +australis (0.0.7) unstable; urgency=medium + + * Upgraded australis to gorealis v2. + * Implemented first version of create feature which takes in a YAML file. + * Added new noun to fetch status called task. Task also has two subcommands, status and config. + + -- Renan DelValle Wed, 26 Dec 2018 15:10:00 -0700 + +australis (0.0.6) unstable; urgency=medium + + * Added auto-completion to the deb file. + * Added set verb and quota noun to set quota resource for certain roles. + * Added JSON output as an option for all commands. + + -- Renan DelValle Wed, 05 Dec 2018 15:10:00 -0700 + +australis (0.0.5) unstable; urgency=medium + + * Backup and snapshot commands have now been moved to under the force subcommand as these are expensive operations + and the subcommand should reflect that. + * Cobra library upgrade. + * Added version command. + * Added ability to use config config file. By default this file will be located in /etc/aurora/australis.yml + * Changed insecureSkipVerify to skipCertVerification + + -- Renan DelValle Wed, 24 Oct 2018 18:27:19 -0700 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..a5e5ab6 --- /dev/null +++ b/debian/control @@ -0,0 +1,10 @@ +Source: australis +Priority: optional +Maintainer: Renan DelValle +Section: utils +Standards-Version: 4.2.1.3 +Homepage: https://github.com/aurora-scheduler/australis + +Package: australis +Architecture: any +Description: Gorealis based command line interface client for Apache Aurora \ No newline at end of file diff --git a/debian/etc/aurora/australis.yml b/debian/etc/aurora/australis.yml new file mode 100644 index 0000000..ffd3283 --- /dev/null +++ b/debian/etc/aurora/australis.yml @@ -0,0 +1,13 @@ +--- + +#username: "aurora" +#password: "secret" +#clientKey: "/path/to/client/key" +#clientCert: "/path/to/client/cert" +#caCertsPath: "/path/to/ca/certs" +#skipCertVerification: true +#scheduler: "http://DirecToScheduler" +#zk: +#- 192.168.3.1 +#- 192.168.3.2 +#- 192.168.3.3 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..15eceab --- /dev/null +++ b/debian/rules @@ -0,0 +1,20 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#DH_VERBOSE = 1 + +%: + dh $@ + +clean: + rm -rf $(CURDIR)/build + rm -rf $(CURDIR)/debian/asutralis + rm -rf $(CURDIR)/debian/australis.debhelper.log + rm -rf $(CURDIR)/debian/debhelper-build-stamp + rm -rf $(CURDIR)/debian/files + rm -rf $(CURDIR)/debian/australis.substvars + +override_dh_auto_build: + mkdir $(CURDIR)/build + /usr/local/go/bin/go build -o build/australis + build/australis autocomplete --filename=build/australis.bash diff --git a/docs/australis.md b/docs/australis.md new file mode 100644 index 0000000..4c257ec --- /dev/null +++ b/docs/australis.md @@ -0,0 +1,44 @@ +## australis + +australis is a client for Apache Aurora + +### Synopsis + +A light-weight command line client for use with Apache Aurora built using gorealis. + +### Options + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -h, --help help for australis + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis create](australis_create.md) - Create an Aurora Job +* [australis fetch](australis_fetch.md) - Fetch information from Aurora +* [australis force](australis_force.md) - Force the scheduler to do a snapshot, a backup, or a task reconciliation. +* [australis kill](australis_kill.md) - Kill an Aurora Job +* [australis monitor](australis_monitor.md) - Watch for a specific state change +* [australis pulse](australis_pulse.md) - Pulse a Job update +* [australis restart](australis_restart.md) - Restart an Aurora Job. +* [australis resume](australis_resume.md) - Resume a Job update +* [australis rollback](australis_rollback.md) - Rollback an operation such as an Update +* [australis schedule](australis_schedule.md) - Schedule a cron job on Aurora scheduler +* [australis set](australis_set.md) - Set a value in the Aurora Scheduler. +* [australis simulate](australis_simulate.md) - Simulate some work based on the current cluster condition, and return the output +* [australis start](australis_start.md) - Start a service, maintenance on a host (DRAIN), a snapshot, an update, or a backup. +* [australis stop](australis_stop.md) - Stop a service or maintenance on a host (DRAIN). + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_autocomplete.md b/docs/australis_autocomplete.md new file mode 100644 index 0000000..dee7b9a --- /dev/null +++ b/docs/australis_autocomplete.md @@ -0,0 +1,47 @@ +## australis autocomplete + +Create auto completion for bash. + +### Synopsis + +Create auto completion bash file for australis. Auto completion file must be placed in the correct +directory in order for bash to pick up the definitions. + +Copy australis.completion.sh into the correct folder and rename to australis + +In Linux, this directory is usually /etc/bash_completion.d/ +In MacOS this directory is $(brew --prefix)/etc/bash_completion.d if auto completion was install through brew. + + +``` +australis autocomplete [flags] +``` + +### Options + +``` + --filename string Path and name of the autocompletion file. (default "australis.completion.sh") + -h, --help help for autocomplete +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora + +###### Auto generated by spf13/cobra on 22-Mar-2019 diff --git a/docs/australis_create.md b/docs/australis_create.md new file mode 100644 index 0000000..dc01c77 --- /dev/null +++ b/docs/australis_create.md @@ -0,0 +1,41 @@ +## australis create + +Create an Aurora Job + +### Synopsis + +Create an Aurora Job + +``` +australis create [flags] +``` + +### Options + +``` + -h, --help help for create + -m, --monitor monitor the result after sending the command (default true) +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_docs.md b/docs/australis_docs.md new file mode 100644 index 0000000..b88f63e --- /dev/null +++ b/docs/australis_docs.md @@ -0,0 +1,39 @@ +## australis docs + +Kill an Aurora Job + +### Synopsis + +Kill an Aurora Job + +``` +australis docs [flags] +``` + +### Options + +``` + -h, --help help for docs +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora + +###### Auto generated by spf13/cobra on 22-Mar-2019 diff --git a/docs/australis_fetch.md b/docs/australis_fetch.md new file mode 100644 index 0000000..8853103 --- /dev/null +++ b/docs/australis_fetch.md @@ -0,0 +1,45 @@ +## australis fetch + +Fetch information from Aurora + +### Synopsis + +Fetch information from Aurora + +### Options + +``` + -h, --help help for fetch +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis fetch capacity](australis_fetch_capacity.md) - Fetch capacity report +* [australis fetch jobs](australis_fetch_jobs.md) - Fetch a list of task Aurora running under a role. +* [australis fetch leader](australis_fetch_leader.md) - Fetch current Aurora leader given Zookeeper nodes. +* [australis fetch master](australis_fetch_master.md) - Fetch current Aurora master nodes/leader given Zookeeper nodes. +* [australis fetch mesos](australis_fetch_mesos.md) - Fetch information from Mesos. +* [australis fetch quota](australis_fetch_quota.md) - Fetch the quotas of given roles +* [australis fetch status](australis_fetch_status.md) - Fetch the maintenance status of a node from Aurora +* [australis fetch task](australis_fetch_task.md) - Task information from Aurora +* [australis fetch tasks](australis_fetch_tasks.md) - Fetch tasks with status + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_capacity.md b/docs/australis_fetch_capacity.md new file mode 100644 index 0000000..d26f37c --- /dev/null +++ b/docs/australis_fetch_capacity.md @@ -0,0 +1,40 @@ +## australis fetch capacity + +Fetch capacity report + +### Synopsis + +This command will show detailed capacity report of the cluster + +``` +australis fetch capacity [flags] +``` + +### Options + +``` + -h, --help help for capacity +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_jobs.md b/docs/australis_fetch_jobs.md new file mode 100644 index 0000000..a150ae4 --- /dev/null +++ b/docs/australis_fetch_jobs.md @@ -0,0 +1,41 @@ +## australis fetch jobs + +Fetch a list of task Aurora running under a role. + +### Synopsis + +To be written. + +``` +australis fetch jobs [flags] +``` + +### Options + +``` + -h, --help help for jobs + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_leader.md b/docs/australis_fetch_leader.md new file mode 100644 index 0000000..0a326b8 --- /dev/null +++ b/docs/australis_fetch_leader.md @@ -0,0 +1,42 @@ +## australis fetch leader + +Fetch current Aurora leader given Zookeeper nodes. + +### Synopsis + +Gets the current leading aurora scheduler instance using information from Zookeeper path. +Pass Zookeeper nodes separated by a space as an argument to this command. + +``` +australis fetch leader [zkNode0, zkNode1, ...zkNodeN] [flags] +``` + +### Options + +``` + -h, --help help for leader + --zkPath string Zookeeper node path where leader election happens (default "/aurora/scheduler") +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_master.md b/docs/australis_fetch_master.md new file mode 100644 index 0000000..9f8da1c --- /dev/null +++ b/docs/australis_fetch_master.md @@ -0,0 +1,42 @@ +## australis fetch master + +Fetch current Aurora master nodes/leader given Zookeeper nodes. + +### Synopsis + +Gets the current aurora master nodes/leader using information from Zookeeper path. +Pass Zookeeper nodes separated by a space as an argument to this command. + +``` +australis fetch master [zkNode0 zkNode1 ...zkNodeN] [flags] +``` + +### Options + +``` + -h, --help help for master + --zkPath string Zookeeper node path to get master nodes/leader (default "/aurora/scheduler") +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_mesos.md b/docs/australis_fetch_mesos.md new file mode 100644 index 0000000..3926905 --- /dev/null +++ b/docs/australis_fetch_mesos.md @@ -0,0 +1,38 @@ +## australis fetch mesos + +Fetch information from Mesos. + +### Synopsis + +Fetch information from Mesos. + +### Options + +``` + -h, --help help for mesos +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora +* [australis fetch mesos leader](australis_fetch_mesos_leader.md) - Fetch current Mesos-master leader given Zookeeper nodes. +* [australis fetch mesos master](australis_fetch_mesos_master.md) - Fetch current Mesos-master nodes/leader given Zookeeper nodes. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_mesos_leader.md b/docs/australis_fetch_mesos_leader.md new file mode 100644 index 0000000..c6557b9 --- /dev/null +++ b/docs/australis_fetch_mesos_leader.md @@ -0,0 +1,43 @@ +## australis fetch mesos leader + +Fetch current Mesos-master leader given Zookeeper nodes. + +### Synopsis + +Gets the current leading Mesos-master instance using information from Zookeeper path. +Pass Zookeeper nodes separated by a space as an argument to this command. If no nodes are provided, +it fetches leader from local Mesos agent or Zookeeper + +``` +australis fetch mesos leader [zkNode0, zkNode1, ...zkNodeN] [flags] +``` + +### Options + +``` + -h, --help help for leader + --zkPath string Zookeeper node path where mesos leader election happens (default "/mesos") +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch mesos](australis_fetch_mesos.md) - Fetch information from Mesos. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_mesos_master.md b/docs/australis_fetch_mesos_master.md new file mode 100644 index 0000000..7f35c9a --- /dev/null +++ b/docs/australis_fetch_mesos_master.md @@ -0,0 +1,43 @@ +## australis fetch mesos master + +Fetch current Mesos-master nodes/leader given Zookeeper nodes. + +### Synopsis + +Gets the current Mesos-master instances using information from Zookeeper path. +Pass Zookeeper nodes separated by a space as an argument to this command. If no nodes are provided, +it fetches Mesos-master nodes/leader from local Mesos agent or Zookeeper + +``` +australis fetch mesos master [zkNode0 zkNode1 ...zkNodeN] [flags] +``` + +### Options + +``` + -h, --help help for master + --zkPath string Zookeeper node path to get mesos master nodes/leader (default "/mesos") +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch mesos](australis_fetch_mesos.md) - Fetch information from Mesos. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_quota.md b/docs/australis_fetch_quota.md new file mode 100644 index 0000000..d3583ff --- /dev/null +++ b/docs/australis_fetch_quota.md @@ -0,0 +1,40 @@ +## australis fetch quota + +Fetch the quotas of given roles + +### Synopsis + +This command will print list of resource quotas with the aggregated resources for the given roles + +``` +australis fetch quota [flags] +``` + +### Options + +``` + -h, --help help for quota +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_status.md b/docs/australis_fetch_status.md new file mode 100644 index 0000000..a80cacf --- /dev/null +++ b/docs/australis_fetch_status.md @@ -0,0 +1,40 @@ +## australis fetch status + +Fetch the maintenance status of a node from Aurora + +### Synopsis + +This command will print the actual status of the mesos agent nodes in Aurora server + +``` +australis fetch status [flags] +``` + +### Options + +``` + -h, --help help for status +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_task.md b/docs/australis_fetch_task.md new file mode 100644 index 0000000..b6ce7c2 --- /dev/null +++ b/docs/australis_fetch_task.md @@ -0,0 +1,38 @@ +## australis fetch task + +Task information from Aurora + +### Synopsis + +Task information from Aurora + +### Options + +``` + -h, --help help for task +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora +* [australis fetch task config](australis_fetch_task_config.md) - Fetch a list of task configurations from Aurora. +* [australis fetch task status](australis_fetch_task_status.md) - Fetch task status for a Job key. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_task_config.md b/docs/australis_fetch_task_config.md new file mode 100644 index 0000000..23b1005 --- /dev/null +++ b/docs/australis_fetch_task_config.md @@ -0,0 +1,43 @@ +## australis fetch task config + +Fetch a list of task configurations from Aurora. + +### Synopsis + +To be written. + +``` +australis fetch task config [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for config + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch task](australis_fetch_task.md) - Task information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_task_status.md b/docs/australis_fetch_task_status.md new file mode 100644 index 0000000..bd44edf --- /dev/null +++ b/docs/australis_fetch_task_status.md @@ -0,0 +1,43 @@ +## australis fetch task status + +Fetch task status for a Job key. + +### Synopsis + +To be written. + +``` +australis fetch task status [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for status + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch task](australis_fetch_task.md) - Task information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_fetch_tasks.md b/docs/australis_fetch_tasks.md new file mode 100644 index 0000000..71dd4a8 --- /dev/null +++ b/docs/australis_fetch_tasks.md @@ -0,0 +1,44 @@ +## australis fetch tasks + +Fetch tasks with status + +### Synopsis + +This command will return the list of tasks with a given status + +``` +australis fetch tasks [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for tasks + -n, --name string Aurora Name + -r, --role string Aurora Role + -x, --status string Task Status +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis fetch](australis_fetch.md) - Fetch information from Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_force.md b/docs/australis_force.md new file mode 100644 index 0000000..420123d --- /dev/null +++ b/docs/australis_force.md @@ -0,0 +1,39 @@ +## australis force + +Force the scheduler to do a snapshot, a backup, or a task reconciliation. + +### Synopsis + +Force the scheduler to do a snapshot, a backup, or a task reconciliation. + +### Options + +``` + -h, --help help for force +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis force backup](australis_force_backup.md) - Force the leading scheduler to perform a Backup. +* [australis force recon](australis_force_recon.md) - Force the leading scheduler to perform a reconciliation. +* [australis force snapshot](australis_force_snapshot.md) - Force the leading scheduler to perform a Snapshot. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_force_backup.md b/docs/australis_force_backup.md new file mode 100644 index 0000000..81ce196 --- /dev/null +++ b/docs/australis_force_backup.md @@ -0,0 +1,41 @@ +## australis force backup + +Force the leading scheduler to perform a Backup. + +### Synopsis + +Force the Aurora Scheduler to write a backup of the latest snapshot to the filesystem +of the leading scheduler. + +``` +australis force backup [flags] +``` + +### Options + +``` + -h, --help help for backup +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis force](australis_force.md) - Force the scheduler to do a snapshot, a backup, or a task reconciliation. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_force_recon.md b/docs/australis_force_recon.md new file mode 100644 index 0000000..b470706 --- /dev/null +++ b/docs/australis_force_recon.md @@ -0,0 +1,45 @@ +## australis force recon + +Force the leading scheduler to perform a reconciliation. + +### Synopsis + +Force the Aurora Scheduler to perform a task reconciliation. +Explicit Recon: +Aurora will send a list of non-terminal task IDs and the master responds +with the latest state for each task, if possible. +Implicit Recon: +Aurora will send an empty list of tasks and the master responds with the latest +state for all currently known non-terminal tasks. + + +### Options + +``` + -h, --help help for recon +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis force](australis_force.md) - Force the scheduler to do a snapshot, a backup, or a task reconciliation. +* [australis force recon explicit](australis_force_recon_explicit.md) - Force the leading scheduler to perform an explicit recon. +* [australis force recon implicit](australis_force_recon_implicit.md) - Force the leading scheduler to perform an implicit recon. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_force_recon_explicit.md b/docs/australis_force_recon_explicit.md new file mode 100644 index 0000000..cbc1be8 --- /dev/null +++ b/docs/australis_force_recon_explicit.md @@ -0,0 +1,42 @@ +## australis force recon explicit + +Force the leading scheduler to perform an explicit recon. + +### Synopsis + +Aurora will send a list of non-terminal task IDs and the master +responds with the latest state for each task, if possible. + + +``` +australis force recon explicit [batch_size] [flags] +``` + +### Options + +``` + -h, --help help for explicit +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis force recon](australis_force_recon.md) - Force the leading scheduler to perform a reconciliation. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_force_recon_implicit.md b/docs/australis_force_recon_implicit.md new file mode 100644 index 0000000..e5b1159 --- /dev/null +++ b/docs/australis_force_recon_implicit.md @@ -0,0 +1,41 @@ +## australis force recon implicit + +Force the leading scheduler to perform an implicit recon. + +### Synopsis + +Forces leading scheduler to ask Mesos Master for a list of the latest state for +all currently known non-terminal tasks being run by Aurora. + +``` +australis force recon implicit [flags] +``` + +### Options + +``` + -h, --help help for implicit +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis force recon](australis_force_recon.md) - Force the leading scheduler to perform a reconciliation. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_force_snapshot.md b/docs/australis_force_snapshot.md new file mode 100644 index 0000000..1e89739 --- /dev/null +++ b/docs/australis_force_snapshot.md @@ -0,0 +1,41 @@ +## australis force snapshot + +Force the leading scheduler to perform a Snapshot. + +### Synopsis + +Takes a Snapshot of the in memory state of the Apache Aurora cluster and +writes it to the Mesos replicated log. This should NOT be confused with a backup. + +``` +australis force snapshot [flags] +``` + +### Options + +``` + -h, --help help for snapshot +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis force](australis_force.md) - Force the scheduler to do a snapshot, a backup, or a task reconciliation. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_kill.md b/docs/australis_kill.md new file mode 100644 index 0000000..0398dac --- /dev/null +++ b/docs/australis_kill.md @@ -0,0 +1,38 @@ +## australis kill + +Kill an Aurora Job + +### Synopsis + +Kill an Aurora Job + +### Options + +``` + -h, --help help for kill +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis kill job](australis_kill_job.md) - Kill an Aurora Job +* [australis kill tasks](australis_kill_tasks.md) - Kill Aurora Tasks + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_kill_job.md b/docs/australis_kill_job.md new file mode 100644 index 0000000..4ca1e6e --- /dev/null +++ b/docs/australis_kill_job.md @@ -0,0 +1,44 @@ +## australis kill job + +Kill an Aurora Job + +### Synopsis + +Kill an Aurora Job + +``` +australis kill job [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for job + -m, --monitor monitor the result after sending the command (default true) + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis kill](australis_kill.md) - Kill an Aurora Job + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_kill_tasks.md b/docs/australis_kill_tasks.md new file mode 100644 index 0000000..274ad4d --- /dev/null +++ b/docs/australis_kill_tasks.md @@ -0,0 +1,45 @@ +## australis kill tasks + +Kill Aurora Tasks + +### Synopsis + +Kill Aurora Tasks + +``` +australis kill tasks [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for tasks + -I, --instances string Instances e.g. 1, 2, 5 + -m, --monitor monitor the result after sending the command (default true) + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis kill](australis_kill.md) - Kill an Aurora Job + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_monitor.md b/docs/australis_monitor.md new file mode 100644 index 0000000..50fea35 --- /dev/null +++ b/docs/australis_monitor.md @@ -0,0 +1,37 @@ +## australis monitor + +Watch for a specific state change + +### Synopsis + +Watch for a specific state change + +### Options + +``` + -h, --help help for monitor +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis monitor hosts](australis_monitor_hosts.md) - Watch a host maintenance status until it enters one of the desired statuses. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_monitor_hosts.md b/docs/australis_monitor_hosts.md new file mode 100644 index 0000000..8264253 --- /dev/null +++ b/docs/australis_monitor_hosts.md @@ -0,0 +1,43 @@ +## australis monitor hosts + +Watch a host maintenance status until it enters one of the desired statuses. + +### Synopsis + +Provide a list of hosts to monitor for desired statuses. Statuses may be passed using the --statuses +flag with a list of comma separated statuses. Statuses include [NONE, SCHEDULED, DRAINED, DRAINING] + +``` +australis monitor hosts [flags] +``` + +### Options + +``` + -h, --help help for hosts + --interval duration Interval at which to poll scheduler. (default 5s) + --statuses strings List of acceptable statuses for a host to be in. (case-insensitive) [NONE, SCHEDULED, DRAINED, DRAINING] (default [DRAINED]) +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis monitor](australis_monitor.md) - Watch for a specific state change + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_pulse.md b/docs/australis_pulse.md new file mode 100644 index 0000000..a152e9b --- /dev/null +++ b/docs/australis_pulse.md @@ -0,0 +1,44 @@ +## australis pulse + +Pulse a Job update + +### Synopsis + +Pulse a Job update + +``` +australis pulse [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for pulse + --id string Update ID + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_restart.md b/docs/australis_restart.md new file mode 100644 index 0000000..81ea511 --- /dev/null +++ b/docs/australis_restart.md @@ -0,0 +1,37 @@ +## australis restart + +Restart an Aurora Job. + +### Synopsis + +Restart an Aurora Job. + +### Options + +``` + -h, --help help for restart +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis restart job](australis_restart_job.md) - Restart a Job. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_restart_job.md b/docs/australis_restart_job.md new file mode 100644 index 0000000..83be678 --- /dev/null +++ b/docs/australis_restart_job.md @@ -0,0 +1,43 @@ +## australis restart job + +Restart a Job. + +### Synopsis + +Restart a Job. + +``` +australis restart job [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for job + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis restart](australis_restart.md) - Restart an Aurora Job. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_restart_tasks.md b/docs/australis_restart_tasks.md new file mode 100644 index 0000000..1f33c79 --- /dev/null +++ b/docs/australis_restart_tasks.md @@ -0,0 +1,45 @@ +## australis restart tasks + +Restart tasks for a Job. + +### Synopsis + +Restart tasks for a Job. + +``` +australis restart tasks [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for tasks + -I, --instances string Instances e.g. 1, 2, 5 + -m, --monitor monitor the result after sending the command (default true) + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis restart](australis_restart.md) - Restart an Aurora Job. + +###### Auto generated by spf13/cobra on 21-Sep-2022 diff --git a/docs/australis_resume.md b/docs/australis_resume.md new file mode 100644 index 0000000..8a63327 --- /dev/null +++ b/docs/australis_resume.md @@ -0,0 +1,45 @@ +## australis resume + +Resume a Job update + +### Synopsis + +Resume a Job update + +``` +australis resume [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for resume + --id string Update ID + --message string Message to store along resume. + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_rollback.md b/docs/australis_rollback.md new file mode 100644 index 0000000..e6a2da9 --- /dev/null +++ b/docs/australis_rollback.md @@ -0,0 +1,37 @@ +## australis rollback + +Rollback an operation such as an Update + +### Synopsis + +Rollback an operation such as an Update + +### Options + +``` + -h, --help help for rollback +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis rollback update](australis_rollback_update.md) - Rollback an update + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_rollback_update.md b/docs/australis_rollback_update.md new file mode 100644 index 0000000..e4dedee --- /dev/null +++ b/docs/australis_rollback_update.md @@ -0,0 +1,45 @@ +## australis rollback update + +Rollback an update + +### Synopsis + +Rollback an update + +``` +australis rollback update [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for update + --id string Update ID + --message string Message to store alongside resume event + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis rollback](australis_rollback.md) - Rollback an operation such as an Update + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_schedule.md b/docs/australis_schedule.md new file mode 100644 index 0000000..7e139ba --- /dev/null +++ b/docs/australis_schedule.md @@ -0,0 +1,40 @@ +## australis schedule + +Schedule a cron job on Aurora scheduler + +### Synopsis + +Schedule a cron job on Aurora scheduler + +``` +australis schedule [flags] +``` + +### Options + +``` + -h, --help help for schedule +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_set.md b/docs/australis_set.md new file mode 100644 index 0000000..f462012 --- /dev/null +++ b/docs/australis_set.md @@ -0,0 +1,37 @@ +## australis set + +Set a value in the Aurora Scheduler. + +### Synopsis + +Set a value in the Aurora Scheduler. + +### Options + +``` + -h, --help help for set +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis set quota](australis_set_quota.md) - Set Quota resources for a role. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_set_quota.md b/docs/australis_set_quota.md new file mode 100644 index 0000000..cf28a6b --- /dev/null +++ b/docs/australis_set_quota.md @@ -0,0 +1,40 @@ +## australis set quota + +Set Quota resources for a role. + +### Synopsis + +Quotas can be set for roles in Aurora. Using this command we can set the resources reserved a role. + +``` +australis set quota cpu: ram: disk: [flags] +``` + +### Options + +``` + -h, --help help for quota +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis set](australis_set.md) - Set a value in the Aurora Scheduler. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_simulate.md b/docs/australis_simulate.md new file mode 100644 index 0000000..33de188 --- /dev/null +++ b/docs/australis_simulate.md @@ -0,0 +1,37 @@ +## australis simulate + +Simulate some work based on the current cluster condition, and return the output + +### Synopsis + +Simulate some work based on the current cluster condition, and return the output + +### Options + +``` + -h, --help help for simulate +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis simulate fit](australis_simulate_fit.md) - Compute how many tasks can we fit to a cluster + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_simulate_fit.md b/docs/australis_simulate_fit.md new file mode 100644 index 0000000..384c96d --- /dev/null +++ b/docs/australis_simulate_fit.md @@ -0,0 +1,40 @@ +## australis simulate fit + +Compute how many tasks can we fit to a cluster + +### Synopsis + +Compute how many tasks can we fit to a cluster + +``` +australis simulate fit [flags] +``` + +### Options + +``` + -h, --help help for fit +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis simulate](australis_simulate.md) - Simulate some work based on the current cluster condition, and return the output + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_start.md b/docs/australis_start.md new file mode 100644 index 0000000..1ca4b1a --- /dev/null +++ b/docs/australis_start.md @@ -0,0 +1,40 @@ +## australis start + +Start a service, maintenance on a host (DRAIN), a snapshot, an update, or a backup. + +### Synopsis + +Start a service, maintenance on a host (DRAIN), a snapshot, an update, or a backup. + +### Options + +``` + -h, --help help for start +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis start drain](australis_start_drain.md) - Place a list of space separated Mesos Agents into draining mode. +* [australis start maintenance](australis_start_maintenance.md) - Place a list of space separated Mesos Agents into maintenance mode. +* [australis start sla-drain](australis_start_sla-drain.md) - Place a list of space separated Mesos Agents into maintenance mode using SLA aware strategies. +* [australis start update](australis_start_update.md) - Start an update on an Aurora long running service. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_start_drain.md b/docs/australis_start_drain.md new file mode 100644 index 0000000..bd16f94 --- /dev/null +++ b/docs/australis_start_drain.md @@ -0,0 +1,46 @@ +## australis start drain + +Place a list of space separated Mesos Agents into draining mode. + +### Synopsis + +Adds a Mesos Agent to Aurora's Drain list. Agents in this list +are not allowed to schedule new tasks and any tasks already running on this Agent +are killed and rescheduled in an Agent that is not in maintenance mode. Command +expects a space separated list of hosts to place into maintenance mode. + +``` +australis start drain [space separated host list or use JSON flags] [flags] +``` + +### Options + +``` + -h, --help help for drain + --interval duration Interval at which to poll scheduler. (default 5s) + --json Read JSON list of agents from the STDIN. + --json-file string JSON file to read list of agents from. +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis start](australis_start.md) - Start a service, maintenance on a host (DRAIN), a snapshot, an update, or a backup. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_start_maintenance.md b/docs/australis_start_maintenance.md new file mode 100644 index 0000000..78b88da --- /dev/null +++ b/docs/australis_start_maintenance.md @@ -0,0 +1,45 @@ +## australis start maintenance + +Place a list of space separated Mesos Agents into maintenance mode. + +### Synopsis + +Places Mesos Agent into Maintenance mode. Agents in this list +are de-prioritized for scheduling a task. Command +expects a space separated list of hosts to place into maintenance mode. + +``` +australis start maintenance [space separated host list or use JSON flags] [flags] +``` + +### Options + +``` + -h, --help help for maintenance + --interval duration Interval at which to poll scheduler. (default 5s) + --json Read JSON list of agents from the STDIN. + --json-file string JSON file to read list of agents from. +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis start](australis_start.md) - Start a service, maintenance on a host (DRAIN), a snapshot, an update, or a backup. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_start_sla-drain.md b/docs/australis_start_sla-drain.md new file mode 100644 index 0000000..cafc961 --- /dev/null +++ b/docs/australis_start_sla-drain.md @@ -0,0 +1,54 @@ +## australis start sla-drain + +Place a list of space separated Mesos Agents into maintenance mode using SLA aware strategies. + +### Synopsis + +Adds a Mesos Agent to Aurora's Drain list. Agents in this list +are not allowed to schedule new tasks and any tasks already running on this Agent +are killed and rescheduled in an Agent that is not in maintenance mode. Command +expects a space separated list of hosts to place into maintenance mode. +If the --count argument is passed, tasks will be drained using the count SLA policy as a fallback +when a Job does not have a defined SLA policy. +If the --percentage argument is passed, tasks will be drained using the percentage SLA policy as a fallback +when a Job does not have a defined SLA policy. + +``` +australis start sla-drain [space separated host list or use JSON flags] [flags] +``` + +### Options + +``` + --count int Instances count that should be running to meet SLA. (default 5) + --duration RUNNING Minimum time duration a task needs to be RUNNING to be treated as active. (default 1m0s) + -h, --help help for sla-drain + --interval duration Interval at which to poll scheduler. (default 10s) + --json Read JSON list of agents from the STDIN. + --json-file string JSON file to read list of agents from. + --percentage float Percentage of instances that should be running to meet SLA. (default 80) + --sla-limit duration Time limit after which SLA-Aware drain sheds SLA Awareness. (default 1h0m0s) +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis start](australis_start.md) - Start a service, maintenance on a host (DRAIN), a snapshot, an update, or a backup. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_start_update.md b/docs/australis_start_update.md new file mode 100644 index 0000000..4bd89f0 --- /dev/null +++ b/docs/australis_start_update.md @@ -0,0 +1,42 @@ +## australis start update + +Start an update on an Aurora long running service. + +### Synopsis + +Starts the update process on an Aurora long running service. If no such service exists, the update mechanism +will act as a deployment, creating all new instances based on the requirements in the update configuration. + +``` +australis start update [update config] [flags] +``` + +### Options + +``` + -h, --help help for update + --interval duration Interval at which to poll scheduler. (default 5s) +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis start](australis_start.md) - Start a service, maintenance on a host (DRAIN), a snapshot, an update, or a backup. + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_stop.md b/docs/australis_stop.md new file mode 100644 index 0000000..eb0c92f --- /dev/null +++ b/docs/australis_stop.md @@ -0,0 +1,38 @@ +## australis stop + +Stop a service or maintenance on a host (DRAIN). + +### Synopsis + +Stop a service or maintenance on a host (DRAIN). + +### Options + +``` + -h, --help help for stop +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis](australis.md) - australis is a client for Apache Aurora +* [australis stop drain](australis_stop_drain.md) - Stop maintenance on a host (move to NONE). +* [australis stop update](australis_stop_update.md) - Stop update + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_stop_drain.md b/docs/australis_stop_drain.md new file mode 100644 index 0000000..9a4ea99 --- /dev/null +++ b/docs/australis_stop_drain.md @@ -0,0 +1,41 @@ +## australis stop drain + +Stop maintenance on a host (move to NONE). + +### Synopsis + +Transition a list of hosts currently in a maintenance status out of it. + +``` +australis stop drain [space separated host list] [flags] +``` + +### Options + +``` + -h, --help help for drain + --interval duration Interval at which to poll scheduler. (default 5s) +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis stop](australis_stop.md) - Stop a service or maintenance on a host (DRAIN). + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/docs/australis_stop_update.md b/docs/australis_stop_update.md new file mode 100644 index 0000000..faa7be9 --- /dev/null +++ b/docs/australis_stop_update.md @@ -0,0 +1,43 @@ +## australis stop update + +Stop update + +### Synopsis + +To be written. + +``` +australis stop update [update ID] [flags] +``` + +### Options + +``` + -e, --environment string Aurora Environment + -h, --help help for update + -n, --name string Aurora Name + -r, --role string Aurora Role +``` + +### Options inherited from parent commands + +``` + -a, --caCertsPath string Path where CA certificates can be found. + -c, --clientCert string Client certificate to use to connect to Aurora. + -k, --clientKey string Client key to use to connect to Aurora. + --config string Config file to use. (default "/etc/aurora/australis.yml") + -l, --logLevel string Set logging level [panic fatal error warning info debug trace]. (default "info") + -p, --password string Password to use for API authentication + -s, --scheduler_addr string Aurora Scheduler's address. + -i, --skipCertVerification Skip CA certificate hostname verification. + -t, --timeout duration Gorealis timeout. (default 20s) + --toJSON Print output in JSON format. + -u, --username string Username to use for API authentication + -z, --zookeeper string Zookeeper node(s) where Aurora stores information. (comma separated list) +``` + +### SEE ALSO + +* [australis stop](australis_stop.md) - Stop a service or maintenance on a host (DRAIN). + +###### Auto generated by spf13/cobra on 8-Sep-2022 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..0fcf130 --- /dev/null +++ b/go.mod @@ -0,0 +1,16 @@ +module github.com/aurora-scheduler/australis + +go 1.15 + +require ( + github.com/aurora-scheduler/gorealis/v2 v2.29.0 + github.com/pkg/errors v0.9.1 + github.com/sirupsen/logrus v1.6.0 + github.com/spf13/cobra v1.0.0 + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.6.3 + github.com/stretchr/testify v1.5.0 + gopkg.in/yaml.v2 v2.2.8 +) + +replace github.com/apache/thrift v0.13.0 => github.com/ridv/thrift v0.13.2 diff --git a/hello_world_docker.yaml b/hello_world_docker.yaml new file mode 100644 index 0000000..8fdaf26 --- /dev/null +++ b/hello_world_docker.yaml @@ -0,0 +1,12 @@ +--- +environment: "prod" +role: "vagrant" +name: "cryptography" +cpu: 2.00 +ram: 256 +disk: 128 +instances: 1 +container: + docker: + name: "rdelvalle/phoronix" + tag: cryptography diff --git a/internal/job.go b/internal/job.go new file mode 100644 index 0000000..b2ffc8b --- /dev/null +++ b/internal/job.go @@ -0,0 +1,216 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package internal + +import ( + "errors" + "strings" + + realis "github.com/aurora-scheduler/gorealis/v2" + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" +) + +type URI struct { + URI string `yaml:"uri"` + Extract bool `yaml:"extract"` + Cache bool `yaml:"cache"` +} + +type Executor struct { + Name string `yaml:"name"` + Data string `yaml:"data"` +} + +type ThermosProcess struct { + Name string `yaml:"name"` + Cmd string `yaml:"cmd"` +} + +type DockerContainer struct { + Name string `yaml:"name"` + Tag string `yaml:"tag"` +} + +type Container struct { + Docker *DockerContainer `yaml:"docker"` +} + +type ValueConstraint struct { + Name string `yaml:"name"` + Values []string `yaml:"values"` + Negated bool `yaml:"negated"` +} + +type LimitConstraint struct { + Name string `yaml:"name"` + Limit int32 `yaml:"limit"` +} + +type Job struct { + Environment string `yaml:"environment"` + Role string `yaml:"role"` + Name string `yaml:"name"` + CPU float64 `yaml:"cpu"` + RAM int64 `yaml:"ram"` + Disk int64 `yaml:"disk"` + Port int64 `yaml:"port"` + GPU int64 `yaml:"gpu"` + Executor Executor `yaml:"executor"` + Instances int32 `yaml:"instances"` + MaxFailures int32 `yaml:"maxFailures"` + URIs []URI `yaml:"uris"` + Metadata map[string]string `yaml:"labels"` + Service bool `yaml:"service"` + Tier string `yaml:"tier,omitempty" default:"preemptible"` + Priority int32 `yaml:"priority"` + Production bool `yaml:"production"` + Thermos []ThermosProcess `yaml:",flow,omitempty"` + Container *Container `yaml:"container,omitempty"` + CronSchedule *string `yaml:"cronSchedule,omitempty"` + CronCollisionPolicy *string `yaml:"cronCollisionPolicy,omitempty"` + ValueConstraints []ValueConstraint `yaml:"valueConstraints,flow,omitempty"` + LimitConstraints []LimitConstraint `yaml:"limitConstraints,flow,omitempty"` +} + +func (j *Job) ToRealis() (*realis.AuroraJob, error) { + auroraJob := realis.NewJob(). + Environment(j.Environment). + Role(j.Role). + Name(j.Name). + CPU(j.CPU). + RAM(j.RAM). + Disk(j.Disk). + AddPorts(int(j.Port)). + IsService(j.Service). + Tier(j.Tier). + Priority(j.Priority). + Production(j.Production). + InstanceCount(j.Instances). + MaxFailure(j.MaxFailures) + + if j.GPU > 0 { + auroraJob.GPU(j.GPU) + } + + if j.CronSchedule != nil { + auroraJob.CronSchedule(*j.CronSchedule) + } + + if j.CronCollisionPolicy != nil { + // Ignoring error because we have already checked for it in the validate function + policy, _ := aurora.CronCollisionPolicyFromString(*j.CronCollisionPolicy) + auroraJob.CronCollisionPolicy(policy) + } + + // Adding URIs. + for _, uri := range j.URIs { + auroraJob.AddURIs(uri.Extract, uri.Cache, uri.URI) + } + + // Adding Metadata. + for key, value := range j.Metadata { + auroraJob.AddLabel(key, value) + } + + // If thermos jobs processes are provided, use them + if len(j.Thermos) > 0 { + thermosExec := realis.ThermosExecutor{} + for _, process := range j.Thermos { + thermosExec.AddProcess(realis.NewThermosProcess(process.Name, process.Cmd)) + } + auroraJob.ThermosExecutor(thermosExec) + } else if j.Executor.Name != "" { + // Non-Thermos executor + if j.Executor.Name == "" { + return nil, errors.New("no executor name provided") + } + + auroraJob.ExecutorName(j.Executor.Name) + auroraJob.ExecutorData(j.Executor.Data) + } else if j.Container != nil { + if j.Container.Docker == nil { + return nil, errors.New("no container specified") + } + + if j.Container.Docker.Tag != "" && !strings.ContainsRune(j.Container.Docker.Name, ':') { + j.Container.Docker.Name += ":" + j.Container.Docker.Tag + } + auroraJob.Container(realis.NewDockerContainer().Image(j.Container.Docker.Name)) + + } + + // Setting Constraints + for _, valConstraint := range j.ValueConstraints { + auroraJob.AddValueConstraint(valConstraint.Name, valConstraint.Negated, valConstraint.Values...) + } + + for _, limit := range j.LimitConstraints { + auroraJob.AddLimitConstraint(limit.Name, limit.Limit) + } + + return auroraJob, nil +} + +func (j *Job) Validate() error { + if j.Name == "" { + return errors.New("job name not specified") + } + + if j.Role == "" { + return errors.New("job role not specified") + } + + if j.Environment == "" { + return errors.New("job environment not specified") + } + + if j.Instances <= 0 { + return errors.New("number of instances in job cannot be less than or equal to 0") + } + + if j.CPU <= 0.0 { + return errors.New("CPU must be greater than 0") + } + + if j.RAM <= 0 { + return errors.New("RAM must be greater than 0") + } + + if j.Disk <= 0 { + return errors.New("disk must be greater than 0") + } + + if len(j.Thermos) == 0 && j.Executor.Name == "" && j.Container == nil { + return errors.New("task does not contain a thermos definition, a custom executor name, or a container to launch") + } + return nil +} + +func (j *Job) ValidateCron() error { + if j.CronSchedule == nil { + return errors.New("cron schedule must be set") + } + + if j.CronCollisionPolicy != nil { + if _, err := aurora.CronCollisionPolicyFromString(*j.CronCollisionPolicy); err != nil { + return err + } + } else { + killExisting := aurora.CronCollisionPolicy_KILL_EXISTING.String() + j.CronCollisionPolicy = &killExisting + } + + return nil +} diff --git a/internal/updateJob.go b/internal/updateJob.go new file mode 100644 index 0000000..4100e8f --- /dev/null +++ b/internal/updateJob.go @@ -0,0 +1,128 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package internal + +import ( + "errors" + "fmt" + "time" + + realis "github.com/aurora-scheduler/gorealis/v2" +) + +type InstanceRange struct { + First int32 `yaml:"first"` + Last int32 `yaml:"last"` +} + +type VariableBatchStrategy struct { + GroupSizes []int32 `yaml:"groupSizes"` + AutoPause bool `yaml:"autoPause"` +} + +type BatchStrategy struct { + GroupSize int32 `yaml:"groupSize"` + AutoPause bool `yaml:"autoPause"` +} + +type QueueStrategy struct { + GroupSize int32 `yaml:"groupSize"` +} + +type UpdateStrategy struct { + VariableBatch *VariableBatchStrategy `yaml:"variableBatch"` + Batch *BatchStrategy `yaml:"batch"` + Queue *QueueStrategy `yaml:"queue"` +} +type UpdateSettings struct { + MaxPerInstanceFailures int32 `yaml:"maxPerInstanceFailures"` + MaxFailedInstances int32 `yaml:"maxFailedInstances"` + MinTimeInRunning time.Duration `yaml:"minTimeInRunning"` + RollbackOnFailure bool `yaml:"rollbackOnFailure"` + InstanceRanges []InstanceRange `yaml:"instanceRanges"` + InstanceCount int32 `yaml:"instanceCount"` + PulseTimeout time.Duration `yaml:"pulseTimeout"` + SLAAware bool `yaml:"slaAware"` + Strategy UpdateStrategy `yaml:"strategy"` +} + +func (u *UpdateSettings) Validate() error { + if u.InstanceCount <= 0 { + return errors.New("instance count must be larger than 0") + } + + if u.Strategy.VariableBatch != nil { + if len(u.Strategy.VariableBatch.GroupSizes) == 0 { + return errors.New("variable batch strategy must specify at least one batch size") + } + for _, batch := range u.Strategy.VariableBatch.GroupSizes { + if batch <= 0 { + return errors.New("all groups in a variable batch strategy must be larger than 0") + } + } + } else if u.Strategy.Batch != nil { + if u.Strategy.Batch.GroupSize <= 0 { + return errors.New("batch strategy must specify a group larger than 0") + } + } else if u.Strategy.Queue != nil { + if u.Strategy.Queue.GroupSize <= 0 { + return errors.New("queue strategy must specify a group larger than 0") + } + } else { + log.Info("No strategy set, falling back on queue strategy with a group size 1") + } + return nil +} + +type UpdateJob struct { + JobConfig Job `yaml:"jobConfig"` + UpdateSettings UpdateSettings `yaml:"updateSettings"` +} + +func (u *UpdateJob) ToRealis() (*realis.JobUpdate, error) { + jobConfig, err := u.JobConfig.ToRealis() + if err != nil { + return nil, fmt.Errorf("invalid job configuration %w", err) + } + + update := realis.JobUpdateFromAuroraTask(jobConfig.AuroraTask()) + + update.MaxPerInstanceFailures(u.UpdateSettings.MaxPerInstanceFailures). + MaxFailedInstances(u.UpdateSettings.MaxFailedInstances). + WatchTime(u.UpdateSettings.MinTimeInRunning). + RollbackOnFail(u.UpdateSettings.RollbackOnFailure). + PulseIntervalTimeout(u.UpdateSettings.PulseTimeout). + SlaAware(u.UpdateSettings.SLAAware). + InstanceCount(u.UpdateSettings.InstanceCount) + + strategy := u.UpdateSettings.Strategy + switch { + case strategy.VariableBatch != nil: + update.VariableBatchStrategy(strategy.VariableBatch.AutoPause, strategy.VariableBatch.GroupSizes...) + case strategy.Batch != nil: + update.BatchUpdateStrategy(strategy.Batch.AutoPause, strategy.Batch.GroupSize) + case strategy.Queue != nil: + update.QueueUpdateStrategy(strategy.Queue.GroupSize) + default: + update.QueueUpdateStrategy(1) + } + + for _, r := range u.UpdateSettings.InstanceRanges { + update.AddInstanceRange(r.First, r.Last) + } + + return update, nil + +} diff --git a/internal/util.go b/internal/util.go new file mode 100644 index 0000000..dbf56be --- /dev/null +++ b/internal/util.go @@ -0,0 +1,161 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package internal + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "time" + + "github.com/aurora-scheduler/gorealis/v2/gen-go/apache/aurora" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + yaml "gopkg.in/yaml.v2" +) + +type MonitorCmdConfig struct { + Cmd *cobra.Command + MonitorInterval, MonitorTimeout time.Duration + StatusList []string +} + +var log *logrus.Logger + +// Logger sets the logger available to the internal package +func Logger(l *logrus.Logger) { + log = l +} + +// ToJSON converts an interface to a JSON formatted string +func ToJSON(v interface{}) string { + output, err := json.Marshal(v) + + if err != nil { + log.Fatalf("Unable to serialize Aurora response: %+v", v) + } + + return string(output) +} + +func GetLoggingLevels() string { + var buffer bytes.Buffer + + for _, level := range logrus.AllLevels { + buffer.WriteString(level.String()) + buffer.WriteString(" ") + } + + buffer.Truncate(buffer.Len() - 1) + + return buffer.String() +} + +func MaintenanceMonitorPrint(hostResult map[string]bool, desiredStates []aurora.MaintenanceMode, toJson bool) { + if len(hostResult) > 0 { + // Create anonymous struct for JSON formatting + output := struct { + DesiredStates []string `json:"desired_states"` + Transitioned []string `json:"transitioned"` + NonTransitioned []string `json:"non-transitioned"` + }{ + make([]string, 0), + make([]string, 0), + make([]string, 0), + } + + for _, state := range desiredStates { + output.DesiredStates = append(output.DesiredStates, state.String()) + } + + for host, ok := range hostResult { + if ok { + output.Transitioned = append(output.Transitioned, host) + } else { + output.NonTransitioned = append(output.NonTransitioned, host) + } + } + + if toJson { + fmt.Println(ToJSON(output)) + } else { + fmt.Printf("Entered %v status: %v\n", output.DesiredStates, output.Transitioned) + fmt.Printf("Did not enter %v status: %v\n", output.DesiredStates, output.NonTransitioned) + } + } +} + +func UnmarshalJob(filename string) (Job, error) { + + job := Job{} + + if jobsFile, err := os.Open(filename); err != nil { + return job, errors.Wrap(err, "unable to read the job config file") + } else { + if err := yaml.NewDecoder(jobsFile).Decode(&job); err != nil { + return job, errors.Wrap(err, "unable to parse job config file") + } + + if err := job.Validate(); err != nil { + return job, fmt.Errorf("invalid job config %w", err) + } + } + + return job, nil +} + +func UnmarshalTaskConfig(filename string) (*aurora.TaskConfig, error) { + if jobsFile, err := os.Open(filename); err != nil { + return nil, errors.Wrap(err, "unable to read the task config file") + } else { + job := Job{} + + if err := yaml.NewDecoder(jobsFile).Decode(&job); err != nil { + return nil, errors.Wrap(err, "unable to parse task config file") + } + + if auroraJob, err := job.ToRealis(); err != nil { + return nil, errors.Wrap(err, "unable to parse task config file") + } else { + return auroraJob.JobConfig().TaskConfig, nil + } + } + + return nil, nil +} + +func UnmarshalUpdate(filename string) (UpdateJob, error) { + + updateJob := UpdateJob{} + + if jobsFile, err := os.Open(filename); err != nil { + return updateJob, errors.Wrap(err, "unable to read the job config file") + } else { + if err := yaml.NewDecoder(jobsFile).Decode(&updateJob); err != nil { + return updateJob, errors.Wrap(err, "unable to parse job config file") + } + + if err := updateJob.JobConfig.Validate(); err != nil { + return updateJob, fmt.Errorf("invalid job config %w", err) + } + if err := updateJob.UpdateSettings.Validate(); err != nil { + return updateJob, fmt.Errorf("invalid update configuration %w", err) + } + } + + return updateJob, nil +} diff --git a/internal/util_test.go b/internal/util_test.go new file mode 100644 index 0000000..366ffb0 --- /dev/null +++ b/internal/util_test.go @@ -0,0 +1,42 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package internal + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUnmarshalJob(t *testing.T) { + _, err := UnmarshalJob("../test/hello_world.yaml") + assert.NoError(t, err) +} + +func TestUnmarshalDedicatedJob(t *testing.T) { + _, err := UnmarshalJob("../test/hello_world_dedicated.yaml") + assert.NoError(t, err) +} + +func TestUnmarshalCron(t *testing.T) { + cron, err := UnmarshalJob("../test/hello_world_cron.yaml") + assert.NoError(t, err) + assert.NoError(t, cron.ValidateCron()) +} + +func TestUnmarshalUpdate(t *testing.T) { + _, err := UnmarshalUpdate("../test/update_hello_world.yaml") + assert.NoError(t, err) +} diff --git a/main.go b/main.go index 7724b03..d32f2c4 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,21 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package main import ( - "github.com/rdelval/australis/cmd" + "github.com/aurora-scheduler/australis/cmd" ) func main() { diff --git a/sampleConifg.australis.yml b/sampleConifg.australis.yml new file mode 100644 index 0000000..66036f7 --- /dev/null +++ b/sampleConifg.australis.yml @@ -0,0 +1,13 @@ +--- + +username: "aurora" +password: "secret" +clientKey: "/path/to/client/key" +clientCert: "/path/to/client/cert" +caCertsPath: "/path/to/ca/certs" +skipCertVerification: true +scheduler: "http://DirecToScheduler" +zk: +- 192.168.3.1 +- 192.168.3.2 +- 192.168.3.3 diff --git a/test/hello_world.yaml b/test/hello_world.yaml new file mode 100644 index 0000000..1e04c24 --- /dev/null +++ b/test/hello_world.yaml @@ -0,0 +1,26 @@ +--- +environment: "prod" +role: "vagrant" +name: "hello_world" +cpu: 0.09 +ram: 64 +disk: 128 +instances: 1 +thermos: + - name: "bootstrap" + cmd: "echo bootstrapping" + - name: "hello_gorealis" + cmd: "while true; do echo hello world from gorealis; sleep 10; done" +updateSettings: + maxPerInstanceFailures: 1 + maxFailedInstances: 1 + minTimeInRunning: 1m + rollbackOnFailure: true + instanceRanges: + - start: 1 + end: 4 + blockIfNoPulseAfter: 1m + slaAware: false + strategy: + name: Batch + groupSize: 2 \ No newline at end of file diff --git a/test/hello_world_cron.yaml b/test/hello_world_cron.yaml new file mode 100644 index 0000000..eab0dce --- /dev/null +++ b/test/hello_world_cron.yaml @@ -0,0 +1,15 @@ +--- +environment: "prod" +role: "vagrant" +name: "hello_world" +cpu: 0.09 +ram: 64 +disk: 128 +instances: 1 +cronSchedule: "*/1 * * * *" +cronCollisionPolicy: "CANCEL_NEW" +thermos: + - name: "bootstrap" + cmd: "echo bootstrapping" + - name: "hello_gorealis" + cmd: "echo hello world from gorealis; sleep 10;" diff --git a/test/hello_world_dedicated.yaml b/test/hello_world_dedicated.yaml new file mode 100644 index 0000000..95dac27 --- /dev/null +++ b/test/hello_world_dedicated.yaml @@ -0,0 +1,30 @@ +--- +environment: "prod" +role: "vagrant" +name: "hello_world" +cpu: 0.09 +ram: 64 +disk: 128 +instances: 1 +valueConstraints: + - name: "dedicated" + values: + - "vagrant/bar" +thermos: + - name: "bootstrap" + cmd: "echo bootstrapping" + - name: "hello_gorealis" + cmd: "while true; do echo hello world from gorealis; sleep 10; done" +updateSettings: + maxPerInstanceFailures: 1 + maxFailedInstances: 1 + minTimeInRunning: 1m + rollbackOnFailure: true + instanceRanges: + - start: 1 + end: 4 + blockIfNoPulseAfter: 1m + slaAware: false + strategy: + name: Batch + groupSize: 2 \ No newline at end of file diff --git a/test/task_config.yaml b/test/task_config.yaml new file mode 100644 index 0000000..addb8c1 --- /dev/null +++ b/test/task_config.yaml @@ -0,0 +1,20 @@ +environment: "prod" +role: "vagrant" +name: "hello_world" +cpu: 0.09 +ram: 64 +disk: 128 +valueConstraints: + - name: "dedicated" + values: + - "vagrant/bar" +limitConstraints: + - name: "host" + limit: 1 + - name: "zone" + limit: 2 +thermos: + - name: "bootstrap" + cmd: "echo bootstrapping" + - name: "hello_gorealis" + cmd: "while true; do echo hello world from gorealis; sleep 10; done" diff --git a/test/update_hello_world.yaml b/test/update_hello_world.yaml new file mode 100644 index 0000000..ae13c27 --- /dev/null +++ b/test/update_hello_world.yaml @@ -0,0 +1,29 @@ +--- +jobConfig: + environment: "prod" + role: "vagrant" + name: "hello_world" + cpu: 0.09 + ram: 64 + disk: 128 + instances: 1 + maxFailures: 1 + thermos: + - name: "bootstrap" + cmd: "echo bootstrapping" + - name: "hello_gorealis" + cmd: "while true; do echo hello world from gorealis; sleep 10; done" +updateSettings: + maxPerInstanceFailures: 1 + maxFailedInstances: 1 + minTimeInRunning: 1m + rollbackOnFailure: true + instanceCount: 1 + instanceRanges: + - first: 1 + last: 4 + pulseTimeout: 1m + strategy: + variableBatch: + groupSizes: [1,2,3] + autoPause: true