Semaphore/db_lib/AnsibleApp.go
Denis Gukov b361695f68
Add app field to template (#1721)
* feat(be): add template app

* feat(be): add field app to template

* fix(be): add app to sql implementation

* refactor(be): extract AnsibleApp class

* refactor(be): rename LocalJobApp -> LocalApp

* feat(app): default app id = empty string

---------

Co-authored-by: fiftin-quiz <157730881+fiftin-quiz@users.noreply.github.com>
2024-01-30 14:26:11 +05:00

158 lines
3.7 KiB
Go

package db_lib
import (
"crypto/md5"
"fmt"
"github.com/ansible-semaphore/semaphore/db"
"github.com/ansible-semaphore/semaphore/lib"
"io"
"io/ioutil"
"os"
"path"
)
func getMD5Hash(filepath string) (string, error) {
file, err := os.Open(filepath)
if err != nil {
return "", err
}
defer file.Close()
hash := md5.New()
if _, err := io.Copy(hash, file); err != nil {
return "", err
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil
}
func hasRequirementsChanges(requirementsFilePath string, requirementsHashFilePath string) bool {
oldFileMD5HashBytes, err := ioutil.ReadFile(requirementsHashFilePath)
if err != nil {
return true
}
newFileMD5Hash, err := getMD5Hash(requirementsFilePath)
if err != nil {
return true
}
return string(oldFileMD5HashBytes) != newFileMD5Hash
}
func writeMD5Hash(requirementsFile string, requirementsHashFile string) error {
newFileMD5Hash, err := getMD5Hash(requirementsFile)
if err != nil {
return err
}
return ioutil.WriteFile(requirementsHashFile, []byte(newFileMD5Hash), 0644)
}
type AnsibleApp struct {
Logger lib.Logger
Playbook *AnsiblePlaybook
Template db.Template
Repository db.Repository
}
func (t *AnsibleApp) SetLogger(logger lib.Logger) {
t.Logger = logger
}
func (t *AnsibleApp) Run(args []string, environmentVars *[]string, cb func(*os.Process)) error {
return t.Playbook.RunPlaybook(args, environmentVars, cb)
}
func (t *AnsibleApp) Log(msg string) {
t.Logger.Log(msg)
}
func (t *AnsibleApp) InstallRequirements() error {
if err := t.installCollectionsRequirements(); err != nil {
return err
}
if err := t.installRolesRequirements(); err != nil {
return err
}
return nil
}
func (t *AnsibleApp) getRepoPath() string {
repo := GitRepository{
Logger: t.Logger,
TemplateID: t.Template.ID,
Repository: t.Repository,
Client: CreateDefaultGitClient(),
}
return repo.GetFullPath()
}
func (t *AnsibleApp) installRolesRequirements() error {
requirementsFilePath := fmt.Sprintf("%s/roles/requirements.yml", t.getRepoPath())
requirementsHashFilePath := fmt.Sprintf("%s.md5", requirementsFilePath)
if _, err := os.Stat(requirementsFilePath); err != nil {
t.Log("No roles/requirements.yml file found. Skip galaxy install process.\n")
return nil
}
if hasRequirementsChanges(requirementsFilePath, requirementsHashFilePath) {
if err := t.runGalaxy([]string{
"role",
"install",
"-r",
requirementsFilePath,
"--force",
}); err != nil {
return err
}
if err := writeMD5Hash(requirementsFilePath, requirementsHashFilePath); err != nil {
return err
}
} else {
t.Log("roles/requirements.yml has no changes. Skip galaxy install process.\n")
}
return nil
}
func (t *AnsibleApp) GetPlaybookDir() string {
playbookPath := path.Join(t.getRepoPath(), t.Template.Playbook)
return path.Dir(playbookPath)
}
func (t *AnsibleApp) installCollectionsRequirements() error {
requirementsFilePath := path.Join(t.GetPlaybookDir(), "collections", "requirements.yml")
requirementsHashFilePath := fmt.Sprintf("%s.md5", requirementsFilePath)
if _, err := os.Stat(requirementsFilePath); err != nil {
t.Log("No collections/requirements.yml file found. Skip galaxy install process.\n")
return nil
}
if hasRequirementsChanges(requirementsFilePath, requirementsHashFilePath) {
if err := t.runGalaxy([]string{
"collection",
"install",
"-r",
requirementsFilePath,
"--force",
}); err != nil {
return err
}
if err := writeMD5Hash(requirementsFilePath, requirementsHashFilePath); err != nil {
return err
}
} else {
t.Log("collections/requirements.yml has no changes. Skip galaxy install process.\n")
}
return nil
}
func (t *AnsibleApp) runGalaxy(args []string) error {
return t.Playbook.RunGalaxy(args)
}