2024-01-30 10:26:11 +01:00
|
|
|
package db_lib
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/md5"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"path"
|
2024-04-12 12:32:54 +02:00
|
|
|
|
|
|
|
"github.com/ansible-semaphore/semaphore/db"
|
|
|
|
"github.com/ansible-semaphore/semaphore/pkg/task_logger"
|
2024-01-30 10:26:11 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
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 {
|
2024-03-10 20:07:19 +01:00
|
|
|
oldFileMD5HashBytes, err := os.ReadFile(requirementsHashFilePath)
|
2024-01-30 10:26:11 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-03-10 20:07:19 +01:00
|
|
|
return os.WriteFile(requirementsHashFile, []byte(newFileMD5Hash), 0644)
|
2024-01-30 10:26:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type AnsibleApp struct {
|
2024-04-12 12:32:54 +02:00
|
|
|
Logger task_logger.Logger
|
2024-01-30 10:26:11 +01:00
|
|
|
Playbook *AnsiblePlaybook
|
|
|
|
Template db.Template
|
|
|
|
Repository db.Repository
|
|
|
|
}
|
|
|
|
|
2024-04-12 12:32:54 +02:00
|
|
|
func (t *AnsibleApp) SetLogger(logger task_logger.Logger) task_logger.Logger {
|
2024-01-30 10:26:11 +01:00
|
|
|
t.Logger = logger
|
2024-03-12 02:20:30 +01:00
|
|
|
t.Playbook.Logger = logger
|
2024-03-12 01:44:04 +01:00
|
|
|
return logger
|
2024-01-30 10:26:11 +01:00
|
|
|
}
|
|
|
|
|
2024-04-05 14:36:04 +02:00
|
|
|
func (t *AnsibleApp) Run(args []string, environmentVars *[]string, inputs map[string]string, cb func(*os.Process)) error {
|
|
|
|
return t.Playbook.RunPlaybook(args, environmentVars, inputs, cb)
|
2024-01-30 10:26:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2024-10-19 22:13:44 +02:00
|
|
|
func (t *AnsibleApp) installGalaxyRequirementsFile(requirementsType GalaxyRequirementsType, requirementsFilePath string) error {
|
2024-05-24 20:13:37 +02:00
|
|
|
|
2024-01-30 10:26:11 +01:00
|
|
|
requirementsHashFilePath := fmt.Sprintf("%s.md5", requirementsFilePath)
|
|
|
|
|
|
|
|
if _, err := os.Stat(requirementsFilePath); err != nil {
|
2024-10-02 12:10:34 +02:00
|
|
|
t.Log("No " + requirementsFilePath + " file found. Skip galaxy install process.\n")
|
2024-01-30 10:26:11 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if hasRequirementsChanges(requirementsFilePath, requirementsHashFilePath) {
|
|
|
|
if err := t.runGalaxy([]string{
|
2024-10-19 22:13:44 +02:00
|
|
|
string(requirementsType),
|
2024-01-30 10:26:11 +01:00
|
|
|
"install",
|
|
|
|
"-r",
|
|
|
|
requirementsFilePath,
|
|
|
|
"--force",
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := writeMD5Hash(requirementsFilePath, requirementsHashFilePath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
2024-10-02 12:10:34 +02:00
|
|
|
t.Log(requirementsFilePath + " has no changes. Skip galaxy install process.\n")
|
2024-01-30 10:26:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *AnsibleApp) GetPlaybookDir() string {
|
|
|
|
playbookPath := path.Join(t.getRepoPath(), t.Template.Playbook)
|
|
|
|
|
|
|
|
return path.Dir(playbookPath)
|
|
|
|
}
|
|
|
|
|
2024-10-19 22:13:44 +02:00
|
|
|
type GalaxyRequirementsType string
|
|
|
|
|
|
|
|
const (
|
|
|
|
GalaxyRole GalaxyRequirementsType = "role"
|
|
|
|
GalaxyCollection GalaxyRequirementsType = "collection"
|
|
|
|
)
|
|
|
|
|
2024-05-24 20:13:37 +02:00
|
|
|
func (t *AnsibleApp) installRolesRequirements() (err error) {
|
2024-10-19 22:13:44 +02:00
|
|
|
err = t.installGalaxyRequirementsFile(GalaxyRole, path.Join(t.GetPlaybookDir(), "roles", "requirements.yml"))
|
2024-05-24 20:13:37 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
2024-01-30 10:26:11 +01:00
|
|
|
}
|
2024-10-19 22:13:44 +02:00
|
|
|
err = t.installGalaxyRequirementsFile(GalaxyRole, path.Join(t.getRepoPath(), "roles", "requirements.yml"))
|
2024-05-24 20:13:37 +02:00
|
|
|
return
|
2024-01-30 10:26:11 +01:00
|
|
|
}
|
|
|
|
|
2024-05-22 11:41:15 +02:00
|
|
|
func (t *AnsibleApp) installCollectionsRequirements() (err error) {
|
2024-10-19 22:13:44 +02:00
|
|
|
err = t.installGalaxyRequirementsFile(GalaxyCollection, path.Join(t.GetPlaybookDir(), "collections", "requirements.yml"))
|
2024-05-22 11:41:15 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2024-10-19 22:13:44 +02:00
|
|
|
err = t.installGalaxyRequirementsFile(GalaxyCollection, path.Join(t.getRepoPath(), "collections", "requirements.yml"))
|
2024-05-22 11:41:15 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-01-30 10:26:11 +01:00
|
|
|
func (t *AnsibleApp) runGalaxy(args []string) error {
|
|
|
|
return t.Playbook.RunGalaxy(args)
|
|
|
|
}
|