Skip to content

Commit 074e303

Browse files
committed
Support TF/Bash (#2077)
Support OpenTofu and Bash
1 parent f144075 commit 074e303

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2499
-131
lines changed

.github/workflows/dev.yml

+31-2
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ jobs:
528528
task e2e:hooks
529529
task e2e:test
530530
531-
deploy-dev:
531+
deploy-server:
532532
runs-on: ubuntu-latest
533533
if: github.repository_owner == 'semaphoreui'
534534

@@ -583,6 +583,35 @@ jobs:
583583
labels: ${{ steps.server.outputs.labels }}
584584
tags: ${{ steps.server.outputs.tags }}
585585

586+
deploy-runner:
587+
runs-on: ubuntu-latest
588+
if: github.repository_owner == 'semaphoreui'
589+
590+
needs:
591+
- integrate-boltdb
592+
- integrate-mysql
593+
- integrate-mariadb
594+
- integrate-postgres
595+
596+
steps:
597+
- name: Checkout source
598+
uses: actions/checkout@v4
599+
600+
- name: Setup qemu
601+
id: qemu
602+
uses: docker/setup-qemu-action@v3
603+
604+
- name: Setup buildx
605+
id: buildx
606+
uses: docker/setup-buildx-action@v3
607+
608+
- name: Hub login
609+
uses: docker/-action@v3
610+
if: github.event_name != 'pull_request'
611+
with:
612+
username: ${{ secrets.DOCKER_USER }}
613+
password: ${{ secrets.DOCKER_PASS }}
614+
586615
- name: Runner meta
587616
id: runner
588617
uses: docker/metadata-action@v5
@@ -604,7 +633,7 @@ jobs:
604633
builder: ${{ steps.buildx.outputs.name }}
605634
context: .
606635
file: deployment/docker/runner/Dockerfile
607-
platforms: linux/amd64,linux/arm64,linux/arm/v6
636+
platforms: linux/amd64,linux/arm64 #,linux/arm/v6
608637
push: ${{ github.event_name != 'pull_request' }}
609638
labels: ${{ steps.runner.outputs.labels }}
610639
tags: ${{ steps.runner.outputs.tags }}

.goreleaser.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ archives:
4141
format: zip
4242

4343
signs:
44-
- artifacts: checksum
45-
args: ["-u", "58A7 CC3D 8A9C A2E5 BB5C 141D 4064 23EA F814 63CA", "--pinentry-mode", "loopback", "--yes", "--batch", "--output", "${signature}", "--detach-sign", "${artifact}"]
44+
-
45+
artifacts: checksum
46+
args: ["-u", "A4FB 7208 48EA 79FA EC4E 9C30 0443 8136 6A5D 4731", "--pinentry-mode", "loopback", "--yes", "--batch", "--output", "${signature}", "--detach-sign", "${artifact}"]
4647

4748
snapshot:
4849
name_template: "{{ .Timestamp }}-{{ .ShortCommit }}-SNAPSHOT"

LICENSE

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2014 Castaway Labs LLC
3+
Copyright (c) 2014-2021 Castaway Labs LLC
4+
Copyright (c) 2021 Denis Gukov
45

56
Permission is hereby granted, free of charge, to any person obtaining a copy
67
of this software and associated documentation files (the "Software"), to deal

README.md

+8-60
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Ansible Semaphore
1+
# Semaphore UI
22

33

44
[![](https://img.shields.io/badge/Telegram-2CA5E0?style=flat-squeare&logo=telegram&logoColor=white)](https://t.me/semaphoreui)
@@ -12,26 +12,14 @@
1212

1313
[//]: # ([![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/fiftin))
1414

15-
Ansible Semaphore is a modern UI for Ansible. It lets you easily run Ansible playbooks, get notifications about fails, control access to deployment system.
15+
Semaphore is a modern UI for Ansible, Terraform/OpenTofu, Bash and Pulumi. It lets you easily run Ansible playbooks, get notifications about fails, control access to deployment system.
1616

17-
If your project has grown and deploying from the terminal is no longer for you then Ansible Semaphore is what you need.
17+
If your project has grown and deploying from the terminal is no longer for you then Semaphore UI is what you need.
1818

1919
![responsive-ui-phone1](https://user-images.githubusercontent.com/914224/134777345-8789d9e4-ff0d-439c-b80e-ddc56b74fcee.png)
2020

2121
## Installation
2222

23-
### Full documentation
24-
https://docs.semui.co/administration-guide/installation
25-
26-
### Snap
27-
28-
[![semaphore](https://snapcraft.io/semaphore/badge.svg)](https://snapcraft.io/semaphore)
29-
30-
```bash
31-
sudo snap install semaphore
32-
sudo semaphore user add --admin --name "Your Name" --login your_login --email your-email@examaple.com --password your_password
33-
```
34-
3523
### Docker
3624

3725
https://hub.docker.com/r/semaphoreui/semaphore
@@ -56,55 +44,15 @@ services:
5644
- /path/to/data/lib:/var/lib/semaphore # database.boltdb location (Not required if using mysql or postgres)
5745
```
5846
47+
### Other installation methods
48+
https://docs.semui.co/administration-guide/installation
49+
5950
## Demo
6051
61-
You can test latest version of Semaphore on https://demo.semui.co.
52+
You can test latest version of Semaphore on https://cloud.semui.co.
6253
6354
## Docs
6455
6556
Admin and user docs: https://docs.semui.co.
6657
67-
API description: https://semui.co/api-docs/.
68-
69-
## Contributing
70-
71-
If you want to write an article about Ansible or Semaphore, contact [@fiftin](https://github.com/fiftin) and we will place your article in our [Blog](https://semui.co/blog/) with link to your profile.
72-
73-
PR's & UX reviews are welcome!
74-
75-
Please follow the [contribution](https://github.com/ansible-semaphore/semaphore/blob/develop/CONTRIBUTING.md) guide. Any questions, please open an issue.
76-
77-
[//]: # (## Release Signing)
78-
79-
[//]: # ()
80-
[//]: # (All releases after 2.5.1 are signed with the gpg public key)
81-
82-
[//]: # (`8CDE D132 5E96 F1D9 EABF 17D4 2C96 CF7D D27F AB82`)
83-
84-
## Support
85-
86-
If you like Ansible Semaphore, you can support the project development on [Ko-fi](https://ko-fi.com/fiftin).
87-
88-
## License
89-
90-
MIT License
91-
92-
Copyright (c) 2016 Castaway Consulting LLC
93-
94-
Permission is hereby granted, free of charge, to any person obtaining a copy
95-
of this software and associated documentation files (the "Software"), to deal
96-
in the Software without restriction, including without limitation the rights
97-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
98-
copies of the Software, and to permit persons to whom the Software is
99-
furnished to do so, subject to the following conditions:
100-
101-
The above copyright notice and this permission notice shall be included in all
102-
copies or substantial portions of the Software.
103-
104-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
105-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
106-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
107-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
108-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
109-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
110-
SOFTWARE.
58+
API description: https://semui.co/api-docs/.

api/helpers/helpers.go

+5
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ func WriteErrorStatus(w http.ResponseWriter, err string, code int) {
9898
}
9999

100100
func WriteError(w http.ResponseWriter, err error) {
101+
if errors.Is(err, tasks.ErrInvalidSubscription) {
102+
WriteErrorStatus(w, "You have no subscription.", http.StatusForbidden)
103+
return
104+
}
105+
101106
if errors.Is(err, db.ErrNotFound) {
102107
w.WriteHeader(http.StatusNotFound)
103108
return

api/projects/inventory.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func AddInventory(w http.ResponseWriter, r *http.Request) {
8484
}
8585

8686
switch inventory.Type {
87-
case db.InventoryStatic, db.InventoryStaticYaml, db.InventoryFile:
87+
case db.InventoryStatic, db.InventoryStaticYaml, db.InventoryFile, db.InventoryTerraformWorkspace:
8888
break
8989
default:
9090
helpers.WriteJSON(w, http.StatusBadRequest, map[string]string{
@@ -170,6 +170,8 @@ func UpdateInventory(w http.ResponseWriter, r *http.Request) {
170170
helpers.WriteErrorStatus(w, "Invalid inventory file pathname. Must be: path/to/inventory.", http.StatusBadRequest)
171171
return
172172
}
173+
case db.InventoryTerraformWorkspace:
174+
break
173175
default:
174176
helpers.WriteErrorStatus(w,
175177
"unknown inventory type: "+string(inventory.Type),

api/projects/tasks.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package projects
22

33
import (
4+
"errors"
45
"github.com/ansible-semaphore/semaphore/api/helpers"
56
"github.com/ansible-semaphore/semaphore/db"
7+
"github.com/ansible-semaphore/semaphore/services/tasks"
68
"github.com/ansible-semaphore/semaphore/util"
79
"github.com/gorilla/context"
810
log "github.com/sirupsen/logrus"
@@ -23,7 +25,11 @@ func AddTask(w http.ResponseWriter, r *http.Request) {
2325

2426
newTask, err := helpers.TaskPool(r).AddTask(taskObj, &user.ID, project.ID)
2527

26-
if err != nil {
28+
if errors.Is(err, tasks.ErrInvalidSubscription) {
29+
helpers.WriteErrorStatus(w, "No active subscription available.", http.StatusForbidden)
30+
return
31+
} else if err != nil {
32+
2733
util.LogErrorWithFields(err, log.Fields{"error": "Cannot write new event to database"})
2834
w.WriteHeader(http.StatusInternalServerError)
2935
return

api/projects/templates.go

+39
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ func AddTemplate(w http.ResponseWriter, r *http.Request) {
7171
return
7272
}
7373

74+
var err error
75+
7476
template.ProjectID = project.ID
7577
newTemplate, err := helpers.Store(r).CreateTemplate(template)
7678

@@ -79,6 +81,43 @@ func AddTemplate(w http.ResponseWriter, r *http.Request) {
7981
return
8082
}
8183

84+
if newTemplate.App.IsTerraform() {
85+
var inv db.Inventory
86+
87+
if newTemplate.InventoryID == nil {
88+
inv, err = helpers.Store(r).CreateInventory(db.Inventory{
89+
Name: newTemplate.Name + " - default",
90+
ProjectID: project.ID,
91+
HolderID: &newTemplate.ID,
92+
Type: db.InventoryTerraformWorkspace,
93+
Inventory: "default",
94+
})
95+
96+
if err != nil {
97+
helpers.WriteError(w, err)
98+
return
99+
}
100+
101+
newTemplate.InventoryID = &inv.ID
102+
err = helpers.Store(r).UpdateTemplate(newTemplate)
103+
104+
} else {
105+
inv, err = helpers.Store(r).GetInventory(project.ID, *newTemplate.InventoryID)
106+
if err != nil {
107+
helpers.WriteError(w, err)
108+
return
109+
}
110+
111+
inv.HolderID = &newTemplate.ID
112+
err = helpers.Store(r).UpdateInventory(inv)
113+
}
114+
115+
if err != nil {
116+
helpers.WriteError(w, err)
117+
return
118+
}
119+
}
120+
82121
helpers.EventLog(r, helpers.EventLogCreate, helpers.EventLogItem{
83122
UserID: helpers.UserFromContext(r).ID,
84123
ProjectID: project.ID,

api/users.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package api
22

33
import (
4-
log "github.com/sirupsen/logrus"
54
"github.com/ansible-semaphore/semaphore/api/helpers"
65
"github.com/ansible-semaphore/semaphore/db"
6+
log "github.com/sirupsen/logrus"
77
"net/http"
88

99
"github.com/ansible-semaphore/semaphore/util"

cli/cmd/root.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ package cmd
22

33
import (
44
"fmt"
5-
"net/http"
6-
"os"
7-
"strings"
8-
95
"github.com/ansible-semaphore/semaphore/api"
106
"github.com/ansible-semaphore/semaphore/api/sockets"
117
"github.com/ansible-semaphore/semaphore/db"
@@ -17,14 +13,17 @@ import (
1713
"github.com/gorilla/handlers"
1814
log "github.com/sirupsen/logrus"
1915
"github.com/spf13/cobra"
16+
"net/http"
17+
"os"
18+
"strings"
2019
)
2120

2221
var configPath string
2322

2423
var rootCmd = &cobra.Command{
2524
Use: "semaphore",
26-
Short: "Ansible Semaphore is a beautiful web UI for Ansible",
27-
Long: `Ansible Semaphore is a beautiful web UI for Ansible.
25+
Short: "Semaphore UI is a beautiful web UI for Ansible",
26+
Long: `Semaphore UI is a beautiful web UI for Ansible.
2827
Source code is available at https://github.com/ansible-semaphore/semaphore.
2928
Complete documentation is available at https://ansible-semaphore.com.`,
3029
Run: func(cmd *cobra.Command, args []string) {

db/Inventory.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ const (
77
InventoryStatic InventoryType = "static"
88
InventoryStaticYaml InventoryType = "static-yaml"
99
// InventoryFile means that it is path to the Ansible inventory file
10-
InventoryFile InventoryType = "file"
10+
InventoryFile InventoryType = "file"
11+
InventoryTerraformWorkspace InventoryType = "terraform-workspace"
12+
InventoryTofuWorkspace InventoryType = "tofu-workspace"
1113
)
1214

1315
// Inventory is the model of an ansible inventory file

db/Template.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@ const (
1515
type TemplateApp string
1616

1717
const (
18-
TemplateAnsible = ""
18+
TemplateAnsible TemplateApp = ""
19+
TemplateTerraform TemplateApp = "terraform"
20+
TemplateTofu TemplateApp = "tofu"
21+
TemplateBash TemplateApp = "bash"
22+
TemplatePulumi TemplateApp = "pulumi"
1923
)
2024

25+
func (t TemplateApp) IsTerraform() bool {
26+
return t == TemplateTerraform || t == TemplateTofu
27+
}
28+
2129
type SurveyVarType string
2230

2331
const (
@@ -102,7 +110,7 @@ func (tpl *Template) Validate() error {
102110
return &ValidationError{"template name can not be empty"}
103111
}
104112

105-
if tpl.Playbook == "" {
113+
if !tpl.App.IsTerraform() && tpl.Playbook == "" {
106114
return &ValidationError{"template playbook can not be empty"}
107115
}
108116

db/sql/option.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (d *SqlDb) SetOption(key string, value string) error {
2424

2525
func (d *SqlDb) getOption(key string) (value string, err error) {
2626
q := squirrel.Select("*").
27-
From(db.OptionProps.TableName).
27+
From("`"+db.OptionProps.TableName+"`").
2828
Where("`key`=?", key)
2929

3030
query, args, err := q.ToSql()

db_lib/AppFactory.go

+20
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ func CreateApp(template db.Template, repository db.Repository, logger task_logge
1818
Logger: logger,
1919
},
2020
}
21+
case db.TemplateTerraform:
22+
return &TerraformApp{
23+
Template: template,
24+
Repository: repository,
25+
Logger: logger,
26+
Name: TerraformAppTerraform,
27+
}
28+
case db.TemplateTofu:
29+
return &TerraformApp{
30+
Template: template,
31+
Repository: repository,
32+
Logger: logger,
33+
Name: TerraformAppTofu,
34+
}
35+
case db.TemplateBash:
36+
return &BashApp{
37+
Template: template,
38+
Repository: repository,
39+
Logger: logger,
40+
}
2141
default:
2242
panic("unknown app")
2343
}

0 commit comments

Comments
 (0)