Commit 999efeb8 authored by Lukas Burgey's avatar Lukas Burgey
Browse files

Extend the task replies towards the backend

This will make the state tracking at the backend much easier

For the future we need an interface change for the scripts so they can
inform us what states the credentials have after the script run
parent 4344557f
......@@ -40,7 +40,7 @@ type (
FetchIntervalString string `json:"fetch_interval"` // string parsed by time.ParseDuration
ReconnectTimeoutString string `json:"reconnect_timeout"` // string parsed by time.ParseDuration
NewTasks chan task
DoneTasks chan taskExecution
DoneTasks chan taskReply
FetchInterval time.Duration
ReconnectTimeout time.Duration
RabbitMQConfig rabbitMQConfig
......@@ -210,7 +210,7 @@ func getConfig(configFile string) (c config, err error) {
// initialize the task queues
c.NewTasks = make(chan task)
c.DoneTasks = make(chan taskExecution)
c.DoneTasks = make(chan taskReply)
return
}
......
......@@ -26,6 +26,7 @@ type (
Name string `json:"name"`
}
// task describes a deployment action
task struct {
ID int `json:"id"`
StateTarget s.State `json:"state_target"`
......@@ -35,7 +36,7 @@ type (
Questionnaire map[string]string `json:"questionnaire"`
Group group `json:"group"`
// maybe overwritten by scheduleTask
// Service may be overwritten by scheduleTask
Service service `json:"service,omitempty"`
// Exchange and RoutingKey are inserted when we receive the task via RabbitMQ
......@@ -43,13 +44,18 @@ type (
RoutingKey string
}
taskExecution struct {
// taskReply is sent back to the backend to inform it about executed deployment actions
taskReply struct {
// ID of the according task (at the backend: DeploymentState)
ID int `json:"id"`
Output s.Output `json:"output"`
// we need to inform the backend for which service we deployed
// Service is the service for which we performed the deploy action
Service service `json:"service"`
// UserCredentials serves to inform, which specific credentials we deployed
// maps credential types to maps of credential names to credential state
UserCredentials map[string]map[string]s.State `json:"user_credentials"`
}
// ackResponse response of the backend for our response
......@@ -70,11 +76,11 @@ func (t task) Log(formatString string, params ...interface{}) {
log.Printf("%s "+formatString, append([]interface{}{t}, params...)...)
}
func (te taskExecution) String() string {
func (te taskReply) String() string {
return fmt.Sprintf("[Task:%v:%v]", te.ID, te.Service.Name)
}
func (te taskExecution) Log(formatString string, params ...interface{}) {
func (te taskReply) Log(formatString string, params ...interface{}) {
log.Printf("%s "+formatString, append([]interface{}{te}, params...)...)
}
......@@ -155,7 +161,7 @@ func (c *config) taskHandler() {
if err := c.handleTask(t); err != nil {
t.Log("Error handling task: %s", err)
c.DoneTasks <- taskExecution{
c.DoneTasks <- taskReply{
ID: t.ID,
Service: t.Service,
Output: s.Output{
......@@ -180,13 +186,13 @@ func (c *config) taskHandler() {
func (c *config) taskResponder() {
for doneTask := range c.DoneTasks {
// ack tasks asynchronously
go func(te taskExecution) {
go func(te taskReply) {
err := c.respondToTask(te)
if err != nil {
te.Log("ACK-ERROR: %s", err)
// reschedule failed responses
go func(te taskExecution) {
go func(te taskReply) {
time.Sleep(time.Minute)
c.DoneTasks <- te
}(te)
......@@ -290,6 +296,7 @@ func (c *config) handleTask(t task) (err error) {
Questionnaire: t.Questionnaire,
Credentials: t.Credentials,
}
iBytes, err := input.Marshal()
if err != nil {
return
......@@ -363,20 +370,40 @@ func (c *config) handleTask(t task) (err error) {
t.Log("Output: %s", output)
}
c.DoneTasks <- taskExecution{
ID: t.ID,
Service: t.Service,
Output: output,
// TODO change the API towards the scripts so the can tell us which credentials they actually deploy
// here we just expect the script to make them all reach the StateTarget
var userCredentials = make(map[string]map[string]s.State)
for credType, credList := range t.Credentials {
for _, credential := range credList {
if stateMap, ok := userCredentials[credType]; !ok {
userCredentials[credType] = map[string]s.State{
credential.Name: t.StateTarget,
}
} else {
stateMap[credential.Name] = t.StateTarget
}
}
}
c.DoneTasks <- taskReply{
ID: t.ID,
Service: t.Service,
Output: output,
UserCredentials: userCredentials,
}
return
}
func (c *config) respondToTask(te taskExecution) (err error) {
func (c *config) respondToTask(te taskReply) (err error) {
taskResponse, err := json.MarshalIndent(te, "", " ")
if err != nil {
return
}
if *backendDebugging {
log.Printf("Replying to the backend: %s", taskResponse)
}
url := fmt.Sprintf("https://%s/backend/clientapi/response", c.Host)
req, err := http.NewRequest("POST", url, bytes.NewReader(taskResponse))
if err != nil {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment