Compare commits
19 Commits
3425330890
...
aee513f786
Author | SHA1 | Date | |
---|---|---|---|
aee513f786 | |||
6b99cfa196 | |||
c24e8086e9 | |||
c12bbe3bee | |||
33febd662e | |||
5635c1edd0 | |||
e169778c82 | |||
c838bfe815 | |||
e81a5def47 | |||
18884c640d | |||
ee2256bfb2 | |||
82d79c520a | |||
c30ae2ac3e | |||
fc738597ff | |||
aebef21eb4 | |||
c660e97434 | |||
d35fdc890d | |||
6fe1f26c71 | |||
5b5568910d |
@ -1,3 +0,0 @@
|
||||
kind: Added
|
||||
body: Command Type Package - allows one to perform package operations [docs](https://backy.cybershell.xyz/config/packages/)
|
||||
time: 2025-01-03T22:40:14.014560779-06:00
|
@ -1,3 +0,0 @@
|
||||
kind: Added
|
||||
body: Exec subcommand `host` allows for parallel execution of commands on hosts. [See docs](https://backy.cybershell.xyz/cli/exec)
|
||||
time: 2025-01-03T23:00:44.417463429-06:00
|
4
.changes/v0.6.0.md
Normal file
4
.changes/v0.6.0.md
Normal file
@ -0,0 +1,4 @@
|
||||
## v0.6.0 - 2025-01-04
|
||||
### Added
|
||||
* Command Type Package - allows one to perform package operations [docs](https://backy.cybershell.xyz/config/packages/)
|
||||
* Exec subcommand `host` allows for parallel execution of commands on hosts. [See docs](https://backy.cybershell.xyz/cli/exec)
|
3
.changes/v0.6.1.md
Normal file
3
.changes/v0.6.1.md
Normal file
@ -0,0 +1,3 @@
|
||||
## v0.6.1 - 2025-01-04
|
||||
### Fixed
|
||||
* Hooks now run explicitly after the command executes. Fixed panic due to improper logic.
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
|
||||
dist/
|
||||
|
||||
.codegpt
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,3 +1,7 @@
|
||||
[submodule "docs/themes/hugo-theme-relearn"]
|
||||
path = docs/themes/hugo-theme-relearn
|
||||
url = https://github.com/McShelby/hugo-theme-relearn.git
|
||||
|
||||
[submodule "docs/themes/plausible-hugo"]
|
||||
path = docs/themes/plausible-hugo
|
||||
url = https://github.com/divinerites/plausible-hugo.git
|
||||
|
@ -1,15 +1,12 @@
|
||||
steps:
|
||||
build:
|
||||
image: klakegg/hugo:ext-debian-ci
|
||||
image: hugomods/hugo:ci
|
||||
commands:
|
||||
- git submodule foreach 'git fetch origin; git checkout $(git describe --tags `git rev-list --tags --max-count=1`);'
|
||||
- cd docs
|
||||
- hugo mod get -u ./...
|
||||
- hugo mod get -u github.com/divinerites/plausible-hugo
|
||||
- hugo mod get -u github.com/McShelby/hugo-theme-relearn@7.3.1
|
||||
- hugo
|
||||
when:
|
||||
- event: push
|
||||
branch: master
|
||||
path: "docs/*"
|
||||
|
||||
deploy:
|
||||
image: codingkoopa/git-rsync-openssh
|
||||
@ -28,7 +25,5 @@ steps:
|
||||
- rsync -atv --delete --progress vangen/ backy@backy.cybershell.xyz:vangen-go
|
||||
secrets: [ ssh_host_key, ssh_deploy_key, ssh_passphrase ]
|
||||
|
||||
when:
|
||||
- event: push
|
||||
branch: master
|
||||
path: "docs/*"
|
||||
when:
|
||||
- branch: master
|
@ -6,6 +6,15 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
||||
and is generated by [Changie](https://github.com/miniscruff/changie).
|
||||
|
||||
|
||||
## v0.6.1 - 2025-01-04
|
||||
### Fixed
|
||||
* When running a list, hooks now run explicitly after the command executes. Fixed panic due to improper logic.
|
||||
|
||||
## v0.6.0 - 2025-01-04
|
||||
### Added
|
||||
* Command Type Package - allows one to perform package operations [docs](https://backy.cybershell.xyz/config/packages/)
|
||||
* Exec subcommand `host` allows for parallel execution of commands on hosts. [See docs](https://backy.cybershell.xyz/cli/exec)
|
||||
|
||||
## v0.5.0 - 2024-11-19
|
||||
### Added
|
||||
* Lists can now go in a file. See docs for more information.
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const versionStr = "0.5.0"
|
||||
const versionStr = "0.6.1"
|
||||
|
||||
var (
|
||||
versionCmd = &cobra.Command{
|
||||
|
137
docs/config.toml
137
docs/config.toml
@ -1,137 +0,0 @@
|
||||
baseURL = 'http://backy.cybershell.xyz/'
|
||||
languageCode = 'en-us'
|
||||
title = 'A tool for commands'
|
||||
|
||||
# Change the default theme to be use when building the site with Hugo
|
||||
theme = [ "hugo-theme-relearn", "plausible-hugo"] # Add this theme to your already existing other themes
|
||||
|
||||
# For search functionality
|
||||
[outputs]
|
||||
home = [ "HTML", "RSS", "PRINT"]
|
||||
|
||||
[module]
|
||||
[[module.imports]]
|
||||
path = "github.com/divinerites/plausible-hugo"
|
||||
|
||||
[params]
|
||||
# This controls whether submenus will be expanded (true), or collapsed (false) in the
|
||||
# menu; if no setting is given, the first menu level is set to false, all others to true;
|
||||
# this can be overridden in the pages frontmatter
|
||||
alwaysopen = false
|
||||
# Prefix URL to edit current page. Will display an "Edit" button on top right hand corner of every page.
|
||||
# Useful to give opportunity to people to create merge request for your doc.
|
||||
# See the config.toml file from this documentation site to have an example.
|
||||
editURL = ""
|
||||
# Description of the site, will be used in meta information
|
||||
description = ""
|
||||
# Shows a checkmark for visited pages on the menu
|
||||
showVisitedLinks = false
|
||||
# Disable search function. It will hide search bar
|
||||
disableSearch = false
|
||||
# Disable search in hidden pages, otherwise they will be shown in search box
|
||||
disableSearchHiddenPages = false
|
||||
# Disables hidden pages from showing up in the sitemap and on Google (et all), otherwise they may be indexed by search engines
|
||||
disableSeoHiddenPages = false
|
||||
# Disables hidden pages from showing up on the tags page although the tag term will be displayed even if all pages are hidden
|
||||
disableTagHiddenPages = false
|
||||
# Javascript and CSS cache are automatically busted when new version of site is generated.
|
||||
# Set this to true to disable this behavior (some proxies don't handle well this optimization)
|
||||
disableAssetsBusting = false
|
||||
# Set this to true if you want to disable generation for generator version meta tags of hugo and the theme;
|
||||
# don't forget to also set Hugo's disableHugoGeneratorInject=true, otherwise it will generate a meta tag into your home page
|
||||
disableGeneratorVersion = false
|
||||
# Set this to true to disable copy-to-clipboard button for inline code.
|
||||
disableInlineCopyToClipBoard = false
|
||||
# A title for shortcuts in menu is set by default. Set this to true to disable it.
|
||||
disableShortcutsTitle = false
|
||||
# If set to false, a Home button will appear below the search bar on the menu.
|
||||
# It is redirecting to the landing page of the current language if specified. (Default is "/")
|
||||
disableLandingPageButton = true
|
||||
# When using mulitlingual website, disable the switch language button.
|
||||
disableLanguageSwitchingButton = false
|
||||
# Hide breadcrumbs in the header and only show the current page title
|
||||
disableBreadcrumb = true
|
||||
# If set to true, hide table of contents menu in the header of all pages
|
||||
disableToc = false
|
||||
# If set to false, load the MathJax module on every page regardless if a MathJax shortcode is present
|
||||
math = true
|
||||
# Specifies the remote location of the MathJax js
|
||||
customMathJaxURL = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
|
||||
# Initialization parameter for MathJax, see MathJax documentation
|
||||
mathJaxInitialize = "{}"
|
||||
# If set to false, load the Mermaid module on every page regardless if a Mermaid shortcode or Mermaid codefence is present
|
||||
mermaid = true
|
||||
# Specifies the remote location of the Mermaid js
|
||||
customMermaidURL = "https://unpkg.com/mermaid/dist/mermaid.min.js"
|
||||
# Initialization parameter for Mermaid, see Mermaid documentation
|
||||
mermaidInitialize = "{ \"theme\": \"default\" }"
|
||||
# If set to false, load the Swagger module on every page regardless if a Swagger shortcode is present
|
||||
disableSwagger = false
|
||||
# Specifies the remote location of the RapiDoc js
|
||||
customSwaggerURL = "https://unpkg.com/rapidoc/dist/rapidoc-min.js"
|
||||
# Initialization parameter for Swagger, see RapiDoc documentation
|
||||
swaggerInitialize = "{ \"theme\": \"light\" }"
|
||||
# Hide Next and Previous page buttons normally displayed full height beside content
|
||||
disableNextPrev = true
|
||||
# Order sections in menu by "weight" or "title". Default to "weight";
|
||||
# this can be overridden in the pages frontmatter
|
||||
ordersectionsby = "weight"
|
||||
|
||||
[[params.themeVariant]]
|
||||
auto = []
|
||||
identifier = 'relearn-auto'
|
||||
name = 'Relearn Light/Dark'
|
||||
|
||||
[[params.themeVariant]]
|
||||
identifier = 'relearn-light'
|
||||
|
||||
[[params.themeVariant]]
|
||||
identifier = 'relearn-dark'
|
||||
|
||||
[[params.themeVariant]]
|
||||
identifier = 'relearn-bright'
|
||||
|
||||
[[params.themeVariant]]
|
||||
auto = ['zen-light', 'zen-dark']
|
||||
identifier = 'zen-auto'
|
||||
name = 'Zen Light/Dark'
|
||||
|
||||
[[params.themeVariant]]
|
||||
identifier = 'zen-light'
|
||||
|
||||
[[params.themeVariant]]
|
||||
identifier = 'zen-dark'
|
||||
|
||||
[[params.themeVariant]]
|
||||
auto = ['learn', 'neon']
|
||||
identifier = 'retro-auto'
|
||||
name = 'Retro Learn/Neon'
|
||||
|
||||
[[params.themeVariant]]
|
||||
identifier = 'neon'
|
||||
|
||||
[[params.themeVariant]]
|
||||
identifier = 'learn'
|
||||
# Change the title separator. Default to "::".
|
||||
titleSeparator = "-"
|
||||
# If set to true, the menu in the sidebar will be displayed in a collapsible tree view. Although the functionality works with old browsers (IE11), the display of the expander icons is limited to modern browsers
|
||||
collapsibleMenu = true
|
||||
# If a single page can contain content in multiple languages, add those here
|
||||
additionalContentLanguage = [ "en" ]
|
||||
# If set to true, no index.html will be appended to prettyURLs; this will cause pages not
|
||||
# to be servable from the file system
|
||||
disableExplicitIndexURLs = false
|
||||
# For external links you can define how they are opened in your browser; this setting will only be applied to the content area but not the shortcut menu
|
||||
externalLinkTarget = "_blank"
|
||||
# Author of the site, will be used in meta information
|
||||
[params.author]
|
||||
name = "Andrew Woodlee"
|
||||
|
||||
|
||||
[params.plausible]
|
||||
enable = true # Whether to enable plausible tracking
|
||||
domain = "backy.cybershell.xyz" # Plausible "domain" name/id in your dashboard
|
||||
outbound_link = true
|
||||
gitstar = false
|
||||
selfhosted_domain = "stats.andrewnw.com" # Self-hosted plausible domain
|
||||
|
78
docs/config.yaml
Normal file
78
docs/config.yaml
Normal file
@ -0,0 +1,78 @@
|
||||
baseURL: https://backy.cybershell.xyz/
|
||||
languageCode: en-us
|
||||
title: A tool for commands
|
||||
theme:
|
||||
- hugo-theme-relearn
|
||||
- plausible-hugo
|
||||
outputs:
|
||||
home:
|
||||
- HTML
|
||||
- RSS
|
||||
- PRINT
|
||||
module:
|
||||
imports:
|
||||
- path: github.com/divinerites/plausible-hugo
|
||||
- path: github.com/McShelby/hugo-theme-relearn
|
||||
params:
|
||||
themeVariant:
|
||||
- auto: []
|
||||
identifier: relearn-auto
|
||||
name: Relearn Light/Dark
|
||||
- identifier: relearn-light
|
||||
- identifier: relearn-dark
|
||||
- identifier: relearn-bright
|
||||
- auto:
|
||||
- zen-light
|
||||
- zen-dark
|
||||
identifier: zen-auto
|
||||
name: Zen Light/Dark
|
||||
- identifier: zen-light
|
||||
- identifier: zen-dark
|
||||
- auto:
|
||||
- learn
|
||||
- neon
|
||||
identifier: retro-auto
|
||||
name: Retro Learn/Neon
|
||||
- identifier: neon
|
||||
- identifier: learn
|
||||
plausible:
|
||||
enable: true
|
||||
domain: backy.cybershell.xyz
|
||||
outbound_link: true
|
||||
gitstar: false
|
||||
selfhosted_domain: stats.andrewnw.com
|
||||
author:
|
||||
name: Andrew Woodlee
|
||||
alwaysopen: false
|
||||
editURL: ""
|
||||
description: ""
|
||||
showVisitedLinks: false
|
||||
disableSearch: false
|
||||
disableSearchHiddenPages: false
|
||||
disableSeoHiddenPages: false
|
||||
disableTagHiddenPages: false
|
||||
disableAssetsBusting: false
|
||||
disableGeneratorVersion: false
|
||||
disableInlineCopyToClipBoard: false
|
||||
disableShortcutsTitle: false
|
||||
disableLandingPageButton: true
|
||||
disableLanguageSwitchingButton: false
|
||||
disableBreadcrumb: true
|
||||
disableToc: false
|
||||
math: true
|
||||
customMathJaxURL: https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
|
||||
mathJaxInitialize: "{}"
|
||||
mermaid: true
|
||||
customMermaidURL: https://unpkg.com/mermaid/dist/mermaid.min.js
|
||||
mermaidInitialize: '{ "theme": "default" }'
|
||||
disableSwagger: false
|
||||
customSwaggerURL: https://unpkg.com/rapidoc/dist/rapidoc-min.js
|
||||
swaggerInitialize: '{ "theme": "light" }'
|
||||
disableNextPrev: true
|
||||
ordersectionsby: weight
|
||||
titleSeparator: "-"
|
||||
collapsibleMenu: true
|
||||
additionalContentLanguage:
|
||||
- en
|
||||
disableExplicitIndexURLs: false
|
||||
externalLinkTarget: _blank
|
@ -17,6 +17,10 @@ Feel free to open a [PR](https://git.andrewnw.xyz/CyberShell/backy/pulls), raise
|
||||
|
||||
- Allows easy configuration of executable commands
|
||||
|
||||
- Allows for running package operations
|
||||
|
||||
- Allows configuring failure, success, and final hooks
|
||||
|
||||
- Allows for commands to be run on many hosts over SSH
|
||||
|
||||
- Commands can be grouped in list to run in specific order
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: Exec
|
||||
---
|
||||
|
||||
The `exec` subcommand can do somethings that the configuration file can't do yet. The command `exec host` can execute commands on many hosts.
|
||||
The `exec` subcommand can do some things that the configuration file can't do yet. The command `exec host` can execute commands on many hosts.
|
||||
|
||||
`exec host` takes the following arguments:
|
||||
|
||||
|
@ -3,6 +3,6 @@ module git.andrewnw.xyz/CyberShell/backy/docs
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20230209073138-890d12ea922d // indirect
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20250103114405-80e448e5bdaa // indirect
|
||||
github.com/divinerites/plausible-hugo v1.21.1 // indirect
|
||||
)
|
||||
|
@ -1,4 +1,10 @@
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20230209073138-890d12ea922d h1:weq1mrQ/qNAvGrNgvZVL1K8adbT3bswZf2ABLr/LCIA=
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20230209073138-890d12ea922d/go.mod h1:mKQQdxZNIlLvAj8X3tMq+RzntIJSr9z7XdzuMomt0IM=
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20241210183303-16d4de84becf h1:bMx4kwM7Q+dAzvSOWs3XWZ25o+n4mI0GPHqzbzeWb3M=
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20241210183303-16d4de84becf/go.mod h1:mKQQdxZNIlLvAj8X3tMq+RzntIJSr9z7XdzuMomt0IM=
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20250102210630-dd0597ffa4b2 h1:sWaC1/dL65v3iRvblEAaBLpKC5TIT0R9JASk1hZNET8=
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20250102210630-dd0597ffa4b2/go.mod h1:mKQQdxZNIlLvAj8X3tMq+RzntIJSr9z7XdzuMomt0IM=
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20250103114405-80e448e5bdaa h1:G+OnMEzK4XOzbbcf1SmaGyOYJ0h5idp/IJdguWs8ioU=
|
||||
github.com/McShelby/hugo-theme-relearn v0.0.0-20250103114405-80e448e5bdaa/go.mod h1:mKQQdxZNIlLvAj8X3tMq+RzntIJSr9z7XdzuMomt0IM=
|
||||
github.com/divinerites/plausible-hugo v1.21.1 h1:ZTWwjhZ0PmLMacCVGlcGiYFEZW7VaYE767tchDskOug=
|
||||
github.com/divinerites/plausible-hugo v1.21.1/go.mod h1:cxr+YB3FUwbLon8KCs4pV4Ankbkq6lJxTQUpNb5KqPo=
|
||||
|
@ -144,115 +144,123 @@ func (command *Command) RunCmd(cmdCtxLogger zerolog.Logger, opts *ConfigOpts) ([
|
||||
return outputArr, nil
|
||||
}
|
||||
|
||||
// cmdListWorker
|
||||
func cmdListWorker(msgTemps *msgTemplates, jobs <-chan *CmdList, results chan<- string, opts *ConfigOpts) {
|
||||
// iterate over list to run
|
||||
res := CmdListResults{}
|
||||
func cmdListWorker(msgTemps *msgTemplates, jobs <-chan *CmdList, results chan<- CmdResult, opts *ConfigOpts) {
|
||||
for list := range jobs {
|
||||
fieldsMap := make(map[string]interface{})
|
||||
fieldsMap["list"] = list.Name
|
||||
fieldsMap := map[string]interface{}{"list": list.Name}
|
||||
var cmdLogger zerolog.Logger
|
||||
|
||||
var count int // count of how many commands have been executed
|
||||
var cmdsRan []string // store the commands that have been executed
|
||||
var outStructArr []outStruct // stores output messages
|
||||
var cmdsRan []string
|
||||
var outStructArr []outStruct
|
||||
var hasError bool // Tracks if any command in the list failed
|
||||
|
||||
for _, cmd := range list.Order {
|
||||
|
||||
currentCmd := opts.Cmds[cmd].Name
|
||||
|
||||
fieldsMap["cmd"] = opts.Cmds[cmd].Name
|
||||
cmdToRun := opts.Cmds[cmd]
|
||||
|
||||
currentCmd := cmdToRun.Name
|
||||
fieldsMap["cmd"] = currentCmd
|
||||
cmdLogger = cmdToRun.GenerateLogger(opts)
|
||||
cmdLogger.Info().Fields(fieldsMap).Send()
|
||||
|
||||
outputArr, runOutErr := cmdToRun.RunCmd(cmdLogger, opts)
|
||||
outputArr, runErr := cmdToRun.RunCmd(cmdLogger, opts)
|
||||
cmdsRan = append(cmdsRan, cmd)
|
||||
|
||||
if list.NotifyConfig != nil {
|
||||
if runErr != nil {
|
||||
|
||||
// check if the command output should be included
|
||||
if cmdToRun.GetOutput || list.GetOutput {
|
||||
outputStruct := outStruct{
|
||||
CmdName: cmdToRun.Name,
|
||||
CmdExecuted: currentCmd,
|
||||
Output: outputArr,
|
||||
}
|
||||
// Log the error and send a failed result
|
||||
cmdLogger.Err(runErr).Send()
|
||||
results <- CmdResult{CmdName: cmd, ListName: list.Name, Error: runErr}
|
||||
|
||||
outStructArr = append(outStructArr, outputStruct)
|
||||
// Execute error hooks for the failed command
|
||||
cmdToRun.ExecuteHooks("error", opts)
|
||||
|
||||
}
|
||||
}
|
||||
count++
|
||||
if runOutErr != nil {
|
||||
res.ErrCmd = cmd
|
||||
// Notify failure
|
||||
if list.NotifyConfig != nil {
|
||||
var errMsg bytes.Buffer
|
||||
errStruct := make(map[string]interface{})
|
||||
|
||||
errStruct["listName"] = list.Name
|
||||
errStruct["Command"] = currentCmd
|
||||
errStruct["Cmd"] = cmd
|
||||
errStruct["Args"] = opts.Cmds[cmd].Args
|
||||
errStruct["Err"] = runOutErr
|
||||
errStruct["CmdsRan"] = cmdsRan
|
||||
errStruct["Output"] = outputArr
|
||||
|
||||
errStruct["CmdOutput"] = outStructArr
|
||||
|
||||
tmpErr := msgTemps.err.Execute(&errMsg, errStruct)
|
||||
|
||||
if tmpErr != nil {
|
||||
cmdLogger.Err(tmpErr).Send()
|
||||
}
|
||||
|
||||
notifySendErr := list.NotifyConfig.Send(context.Background(), fmt.Sprintf("List %s failed", list.Name), errMsg.String())
|
||||
|
||||
if notifySendErr != nil {
|
||||
cmdLogger.Err(notifySendErr).Send()
|
||||
}
|
||||
notifyError(cmdLogger, msgTemps, list, cmdsRan, outStructArr, runErr, cmdToRun, opts)
|
||||
}
|
||||
|
||||
cmdLogger.Err(runOutErr).Send()
|
||||
|
||||
hasError = true
|
||||
break
|
||||
} else {
|
||||
}
|
||||
|
||||
cmdsRan = append(cmdsRan, cmd)
|
||||
|
||||
if count == len(list.Order) {
|
||||
var successMsg bytes.Buffer
|
||||
|
||||
// if notification config is not nil, and NotifyOnSuccess is true or GetOuput is true,
|
||||
// then send notification
|
||||
if list.NotifyConfig != nil && (list.NotifyOnSuccess || list.GetOutput) {
|
||||
successStruct := make(map[string]interface{})
|
||||
|
||||
successStruct["listName"] = list.Name
|
||||
successStruct["CmdsRan"] = cmdsRan
|
||||
|
||||
successStruct["CmdOutput"] = outStructArr
|
||||
|
||||
tmpErr := msgTemps.success.Execute(&successMsg, successStruct)
|
||||
|
||||
if tmpErr != nil {
|
||||
cmdLogger.Err(tmpErr).Send()
|
||||
break
|
||||
}
|
||||
|
||||
err := list.NotifyConfig.Send(context.Background(), fmt.Sprintf("List %s succeeded", list.Name), successMsg.String())
|
||||
|
||||
if err != nil {
|
||||
cmdLogger.Err(err).Send()
|
||||
}
|
||||
}
|
||||
}
|
||||
// Collect output if required
|
||||
if list.GetOutput || cmdToRun.GetOutput {
|
||||
outStructArr = append(outStructArr, outStruct{
|
||||
CmdName: currentCmd,
|
||||
CmdExecuted: currentCmd,
|
||||
Output: outputArr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
results <- res.ErrCmd
|
||||
}
|
||||
// Notify success if no errors occurred
|
||||
if !hasError && list.NotifyConfig != nil && (list.NotifyOnSuccess || list.GetOutput) {
|
||||
notifySuccess(cmdLogger, msgTemps, list, cmdsRan, outStructArr)
|
||||
}
|
||||
|
||||
// Execute success and final hooks for all commands
|
||||
for _, cmd := range list.Order {
|
||||
cmdToRun := opts.Cmds[cmd]
|
||||
|
||||
// Execute success hooks if the command succeeded
|
||||
if !hasError || cmdsRanContains(cmd, cmdsRan) {
|
||||
cmdToRun.ExecuteHooks("success", opts)
|
||||
}
|
||||
|
||||
// Execute final hooks for every command
|
||||
cmdToRun.ExecuteHooks("final", opts)
|
||||
}
|
||||
|
||||
// Send the final result for the list
|
||||
if hasError {
|
||||
results <- CmdResult{CmdName: cmdsRan[len(cmdsRan)-1], ListName: list.Name, Error: fmt.Errorf("list execution failed")}
|
||||
} else {
|
||||
results <- CmdResult{CmdName: cmdsRan[len(cmdsRan)-1], ListName: list.Name, Error: nil}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to check if a command is in the list of executed commands
|
||||
func cmdsRanContains(cmd string, cmdsRan []string) bool {
|
||||
for _, c := range cmdsRan {
|
||||
if c == cmd {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Helper to notify errors
|
||||
func notifyError(logger zerolog.Logger, templates *msgTemplates, list *CmdList, cmdsRan []string, outStructArr []outStruct, err error, cmd *Command, opts *ConfigOpts) {
|
||||
errStruct := map[string]interface{}{
|
||||
"listName": list.Name,
|
||||
"CmdsRan": cmdsRan,
|
||||
"CmdOutput": outStructArr,
|
||||
"Err": err,
|
||||
"Command": cmd.Name,
|
||||
"Args": cmd.Args,
|
||||
}
|
||||
var errMsg bytes.Buffer
|
||||
if e := templates.err.Execute(&errMsg, errStruct); e != nil {
|
||||
logger.Err(e).Send()
|
||||
return
|
||||
}
|
||||
if e := list.NotifyConfig.Send(context.Background(), fmt.Sprintf("List %s failed", list.Name), errMsg.String()); e != nil {
|
||||
logger.Err(e).Send()
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to notify success
|
||||
func notifySuccess(logger zerolog.Logger, templates *msgTemplates, list *CmdList, cmdsRan []string, outStructArr []outStruct) {
|
||||
successStruct := map[string]interface{}{
|
||||
"listName": list.Name,
|
||||
"CmdsRan": cmdsRan,
|
||||
"CmdOutput": outStructArr,
|
||||
}
|
||||
var successMsg bytes.Buffer
|
||||
if e := templates.success.Execute(&successMsg, successStruct); e != nil {
|
||||
logger.Err(e).Send()
|
||||
return
|
||||
}
|
||||
if e := list.NotifyConfig.Send(context.Background(), fmt.Sprintf("List %s succeeded", list.Name), successMsg.String()); e != nil {
|
||||
logger.Err(e).Send()
|
||||
}
|
||||
}
|
||||
|
||||
// RunListConfig runs a command list from the ConfigFile.
|
||||
@ -263,51 +271,40 @@ func (opts *ConfigOpts) RunListConfig(cron string) {
|
||||
}
|
||||
configListsLen := len(opts.CmdConfigLists)
|
||||
listChan := make(chan *CmdList, configListsLen)
|
||||
results := make(chan string)
|
||||
results := make(chan CmdResult, configListsLen)
|
||||
|
||||
// This starts up list workers, initially blocked
|
||||
// because there are no jobs yet.
|
||||
// Start workers
|
||||
for w := 1; w <= configListsLen; w++ {
|
||||
go cmdListWorker(mTemps, listChan, results, opts)
|
||||
}
|
||||
|
||||
// Enqueue jobs
|
||||
for listName, cmdConfig := range opts.CmdConfigLists {
|
||||
if cmdConfig.Name == "" {
|
||||
cmdConfig.Name = listName
|
||||
}
|
||||
if cron != "" {
|
||||
if cron == cmdConfig.Cron {
|
||||
listChan <- cmdConfig
|
||||
}
|
||||
} else {
|
||||
if cron == "" || cron == cmdConfig.Cron {
|
||||
listChan <- cmdConfig
|
||||
}
|
||||
}
|
||||
close(listChan)
|
||||
|
||||
// Process results
|
||||
for a := 1; a <= configListsLen; a++ {
|
||||
l := <-results
|
||||
|
||||
opts.Logger.Debug().Msg(l)
|
||||
|
||||
if l != "" {
|
||||
// execute error hooks
|
||||
opts.Logger.Debug().Msg("hooks are working")
|
||||
opts.Cmds[l].ExecuteHooks("error", opts)
|
||||
} else {
|
||||
// execute success hooks
|
||||
opts.Cmds[l].ExecuteHooks("success", opts)
|
||||
|
||||
}
|
||||
|
||||
// execute final hooks
|
||||
opts.Cmds[l].ExecuteHooks("final", opts)
|
||||
result := <-results
|
||||
opts.Logger.Debug().Msgf("Processing result for list %s, command %s", result.ListName, result.CmdName)
|
||||
|
||||
// Process final hooks for the list (already handled in worker)
|
||||
}
|
||||
|
||||
opts.closeHostConnections()
|
||||
}
|
||||
|
||||
type CmdResult struct {
|
||||
CmdName string // Name of the command executed
|
||||
ListName string // Name of the command list
|
||||
Error error // Error encountered, if any
|
||||
}
|
||||
|
||||
func (config *ConfigOpts) ExecuteCmds(opts *ConfigOpts) {
|
||||
for _, cmd := range opts.executeCmds {
|
||||
cmdToRun := opts.Cmds[cmd]
|
||||
|
Loading…
x
Reference in New Issue
Block a user