Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions cmd/activate.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ hossted activate
err := compose.ActivateCompose()
if err != nil {
fmt.Println(err)
return
}
err = compose.SetCrontabCompose()
if err != nil {
fmt.Println("error in setting crontab for compose: ", err)
return
}
return

} else if activate_type == "standby" {
err := service.InstallOperatorStandbymode()
if err != nil {
Expand Down
28 changes: 28 additions & 0 deletions cmd/reconcileCompose.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
"github.com/hossted/cli/hossted"
"github.com/spf13/cobra"
)

// reconcileComposeCmd represents the reconcileCompose command
var reconcileComposeCmd = &cobra.Command{
Use: "reconcile-compose",
Short: `[rc] hossted set reconcile compose - Set reconciler for the compose`,
Long: ` [rc] hossted set reconcile compose - Set reconciler for the compose`,
Aliases: []string{"rc"},
Example: `
hossted reconcile-compose
`,
Run: func(cmd *cobra.Command, args []string) {
hossted.ReconcileCompose()

},
}

func init() {
rootCmd.AddCommand(reconcileComposeCmd)
}
39 changes: 39 additions & 0 deletions hossted/reconcileCompose.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package hossted

import (
"fmt"

"github.com/hossted/cli/hossted/service/common"
"github.com/hossted/cli/hossted/service/compose"
)

func ReconcileCompose() error {
emailID, err := common.GetEmail()
if err != nil {
return err
}

resp, err := common.GetLoginResponse()
if err != nil {
return err
}

// get OrgID and HosstedApiUrl
orgID, hosstedAPIUrl, err := compose.GetOrgIDHosstedApiUrl()
if err != nil {
fmt.Println(err)
return err
}

/*
================================ TBD: To be discussed ================================
sendComposeInfo inside compose.ComposeReconciler uses HOSSTED_API_URL env variable which will not
be present during cron ReconcileCompose. So for now, the below function is not sending compose info.
*/
err = compose.ComposeReconciler(orgID, emailID, hosstedAPIUrl, resp.Token)
if err != nil {
return err
}

return nil
}
21 changes: 21 additions & 0 deletions hossted/service/common/create_crontab.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package common

import (
"fmt"
"os"
"os/exec"
)

func CreateCrontab(command string, minute string) {
cronTime := fmt.Sprintf("%s * * * *", minute)
var cronJob string = "" + cronTime + " " + command

cmd := exec.Command("bash", "-c", `crontab -l | grep -q '`+command+`' && echo '`+command+` already running' || ((crontab -l; echo "`+cronJob+`") | crontab - && echo '`+command+` configured.')`)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
}
34 changes: 33 additions & 1 deletion hossted/service/compose/activate_compose.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package compose

import (
"fmt"
"os"
"path/filepath"

"github.com/hossted/cli/hossted/service/common"
"gopkg.in/yaml.v2"
)

type OsInfo struct {
OsUUID string `yaml:"osUUID"`
EmailID string `yaml:"emailId,omitempty"`
ClusterRegisteration bool `yaml:"clusterRegisteration,omitempty"`
OrgID string `yaml:"orgID,omitempty"`
HosstedApiUrl string `yaml:"hosstedAPIUrl,omitempty"`
}

type AppRequest struct {
Expand Down Expand Up @@ -63,7 +70,9 @@ func ActivateCompose() error {
return err
}

err = reconcileCompose(orgID, emailID, resp.Token)
hosstedAPIUrl := os.Getenv("HOSSTED_API_URL")

err = ComposeReconciler(orgID, emailID, hosstedAPIUrl, resp.Token)
if err != nil {
return err
}
Expand All @@ -72,6 +81,29 @@ func ActivateCompose() error {

}

func GetOrgIDHosstedApiUrl() (string, string, error) {
//read file
homeDir, err := os.UserHomeDir()

folderPath := filepath.Join(homeDir, ".hossted")
if err != nil {
return "", "", err
}

fileData, err := os.ReadFile(folderPath + "/" + "compose.yaml")
if err != nil {
return "", "", fmt.Errorf("unable to read %s file", folderPath+"/compose.yaml")
}

var osInfo OsInfo
err = yaml.Unmarshal(fileData, &osInfo)
if err != nil {
return "", "", err
}

return osInfo.OrgID, osInfo.HosstedApiUrl, nil
}

// provide prompt to enable monitoring and vulnerability scan

//
Expand Down
72 changes: 36 additions & 36 deletions hossted/service/compose/reconcile_compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"gopkg.in/yaml.v2"
)

func reconcileCompose(orgID, emailID, token string) error {
func ComposeReconciler(orgID, emailID, hosstedAPIUrl, token string) error {

osFilePath, err := getComposeFilePath("compose.yaml")
if err != nil {
Expand All @@ -33,7 +33,7 @@ func reconcileCompose(orgID, emailID, token string) error {
return err
}

osUuid, err := setClusterUUID(emailID, osFilePath)
osUuid, err := setClusterUUID(orgID, emailID, hosstedAPIUrl, osFilePath)
if err != nil {
return err
}
Expand All @@ -43,14 +43,17 @@ func reconcileCompose(orgID, emailID, token string) error {
return err
}

err = writeComposeRequest2File(appFilePath, list, osUuid, emailID)
isComposeStateChange, err := writeComposeRequest2File(appFilePath, list, osUuid, emailID)
if err != nil {
return err
}

err = sendComposeInfo(appFilePath, token, orgID)
if err != nil {
return err
if isComposeStateChange {
// send compose info
err = sendComposeInfo(appFilePath, token, orgID, hosstedAPIUrl)
if err != nil {
return err
}
}

return nil
Expand Down Expand Up @@ -105,10 +108,10 @@ func writeFile(filePath string, data []byte) error {

}

func setClusterUUID(email string, osFilePath string) (string, error) {
func setClusterUUID(orgID, email, hosstedAPIUrl, osFilePath string) (string, error) {
var uuid string
if _, err := os.Stat(osFilePath); os.IsNotExist(err) {
uuid, err = updateUUID(osFilePath, email)
uuid, err = updateUUID(orgID, email, hosstedAPIUrl, osFilePath)
if err != nil {
return uuid, err
}
Expand All @@ -120,7 +123,7 @@ func setClusterUUID(email string, osFilePath string) (string, error) {
return uuid, err
}
if uuid == "" {
uuid, err = updateUUID(osFilePath, email)
uuid, err = updateUUID(orgID, email, hosstedAPIUrl, osFilePath)
if err != nil {
return uuid, err
}
Expand All @@ -129,12 +132,14 @@ func setClusterUUID(email string, osFilePath string) (string, error) {
return uuid, nil
}

func updateUUID(osFilePath string, email string) (string, error) {
func updateUUID(orgID, email, hosstedAPIUrl, osFilePath string) (string, error) {
osUUID := "D-" + uuid.NewString()
fmt.Println("Generating UUID for cluster: ", osUUID)
info := OsInfo{
OsUUID: osUUID,
EmailID: email,
OsUUID: osUUID,
EmailID: email,
OrgID: orgID,
HosstedApiUrl: hosstedAPIUrl,
}

yamlData, err := yaml.Marshal(info)
Expand Down Expand Up @@ -168,26 +173,26 @@ func checkUUID(osFilePath string) (string, error) {
return osData.OsUUID, nil
}

func writeComposeRequest2File(appFilePath string, containerList []types.Container, osUuid string, email string) error {
func writeComposeRequest2File(appFilePath string, containerList []types.Container, osUuid string, email string) (bool, error) {
// prepare appsInfo with updated container status
appRequest, err := prepareComposeRequest(appFilePath, containerList, osUuid, email)
appRequest, isComposeStateChange, err := prepareComposeRequest(appFilePath, containerList, osUuid, email)
if err != nil {
return err
return isComposeStateChange, err
}

jsonData, err := json.MarshalIndent(appRequest, "", " ")
if err != nil {
fmt.Printf("error marshaling JSON: %s\n", err)
return err
return isComposeStateChange, err
}

// write compose status file
err = writeFile(appFilePath, jsonData)
if err != nil {
return err
return isComposeStateChange, err
}

return nil
return isComposeStateChange, nil
}

type optionsState struct {
Expand Down Expand Up @@ -223,14 +228,14 @@ type dockerInstance struct {
Image string `json:"image"`
}

func sendComposeInfo(appFilePath, token, orgID string) error {
func sendComposeInfo(appFilePath, token, orgID, hosstedAPIUrl string) error {
composeInfo, err := readFile(appFilePath)
if err != nil {
return err
}

composeUrl := os.Getenv("HOSSTED_API_URL") + "/compose/hosts"
containersUrl := os.Getenv("HOSSTED_API_URL") + "/compose/containers"
composeUrl := hosstedAPIUrl + "/compose/hosts"
containersUrl := hosstedAPIUrl + "/compose/containers"

var data map[string]AppRequest
err = json.Unmarshal(composeInfo, &data)
Expand Down Expand Up @@ -277,13 +282,7 @@ func sendComposeInfo(appFilePath, token, orgID string) error {
fmt.Printf("Successfully registered app [%s] with appID [%s]\n", appName, compose.AppAPIInfo.AppUUID)
}

var ar map[string]AppRequest
err = json.Unmarshal(composeInfo, &ar)
if err != nil {
return err
}

for appName, info := range ar {
for appName, info := range data {
for _, ci := range info.AppInfo.DockerInstance {
newDI := dockerInstance{
DockerID: ci.DockerID,
Expand Down Expand Up @@ -371,27 +370,28 @@ func getUniqueComposeProjects(containerList []types.Container) (map[string]bool,
return uniqueProjects, nil
}

func prepareComposeRequest(appFilePath string, containerList []types.Container, osUuid string, email string) (map[string]AppRequest, error) {
func prepareComposeRequest(appFilePath string, containerList []types.Container, osUuid string, email string) (map[string]AppRequest, bool, error) {
var appsData map[string]AppRequest
isComposeStateChange := false

if _, err := os.Stat(appFilePath); os.IsNotExist(err) {
appsData = make(map[string]AppRequest)
} else {
data, err := readFile(appFilePath)
if err != nil {
fmt.Printf("Error in reading %s file: %s\n", appFilePath, err)
return appsData, err
return appsData, isComposeStateChange, err
}
err = json.Unmarshal(data, &appsData)
if err != nil {
fmt.Printf("Error in JSON unmarshaling %s file: %s\n", appFilePath, err)
return appsData, err
return appsData, isComposeStateChange, err
}
}

uniqueProjects, err := getUniqueComposeProjects(containerList)
if err != nil {
return appsData, err
return appsData, isComposeStateChange, err
}

// Create a slice of existing apps
Expand All @@ -404,7 +404,7 @@ func prepareComposeRequest(appFilePath string, containerList []types.Container,
var composeFileContent string
list, err := listProjectContainers(project)
if err != nil {
return appsData, err
return appsData, isComposeStateChange, err
}

// Check if project is present in the existingApps
Expand Down Expand Up @@ -458,7 +458,7 @@ func prepareComposeRequest(appFilePath string, containerList []types.Container,
AppAPIInfo: appsData[project].AppAPIInfo,
AppInfo: newComposeRequest,
}
// send http patch request
isComposeStateChange = true
}
} else {
// create AppAPIInfo
Expand Down Expand Up @@ -511,11 +511,11 @@ func prepareComposeRequest(appFilePath string, containerList []types.Container,
AppAPIInfo: appAPIInfo,
AppInfo: newComposeRequest,
}

isComposeStateChange = true
}
}

return appsData, nil
return appsData, isComposeStateChange, nil
}

// GetCPUUsage returns the average CPU usage percentage as a formatted string
Expand Down
12 changes: 12 additions & 0 deletions hossted/service/compose/set_crontab_compose.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package compose

import (
"github.com/hossted/cli/hossted/service/common"
)

func SetCrontabCompose() error {
command := "/usr/local/bin/hossted reconcile-compose 2>&1 | logger -t mycmd"
minute := "*/1"
common.CreateCrontab(command, minute)
return nil
}