Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ACS
Public
Cloud
MAS
clonemap
Commits
5f99fa19
Commit
5f99fa19
authored
Jul 10, 2020
by
Stefan Dähling
Browse files
add module liveness probe
parent
3945a56b
Pipeline
#306146
failed with stages
in 3 minutes and 7 seconds
Changes
11
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
pkg/ams/ams_test.go
View file @
5f99fa19
...
...
@@ -135,17 +135,17 @@ func dummyClient(s *http.Server, t *testing.T) {
DF
:
false
,
},
ImageGroups
:
[]
schemas
.
ImageGroupSpec
{
schemas
.
ImageGroupSpec
{
{
Config
:
schemas
.
ImageGroupConfig
{
Image
:
"agent"
,
PullSecret
:
""
,
},
Agents
:
[]
schemas
.
AgentSpec
{
schemas
.
AgentSpec
{
{
Name
:
"test1"
,
AType
:
"test"
,
},
schemas
.
AgentSpec
{
{
Name
:
"test2"
,
AType
:
"test"
,
},
...
...
pkg/ams/client/client.go
View file @
5f99fa19
...
...
@@ -67,6 +67,17 @@ var httpClient = &http.Client{Timeout: time.Second * 60}
var
delay
=
time
.
Second
*
1
var
numRetries
=
4
// Alive tests if alive
func
Alive
()
(
alive
bool
)
{
alive
=
false
_
,
httpStatus
,
err
:=
httpretry
.
Get
(
httpClient
,
"http://"
+
Host
+
":"
+
strconv
.
Itoa
(
Port
)
+
"/api/alive"
,
time
.
Second
*
2
,
2
)
if
err
==
nil
&&
httpStatus
==
http
.
StatusOK
{
alive
=
true
}
return
}
// GetCloneMAP requests CloneMAP information
func
GetCloneMAP
()
(
cmap
schemas
.
CloneMAP
,
httpStatus
int
,
err
error
)
{
var
body
[]
byte
...
...
pkg/ams/handler.go
View file @
5f99fa19
...
...
@@ -71,6 +71,9 @@ func (ams *AMS) handleAPI(w http.ResponseWriter, r *http.Request) {
if
respath
[
2
]
==
"clonemap"
{
cmapErr
,
httpErr
=
ams
.
handleCloneMAP
(
w
,
r
)
resvalid
=
true
}
else
if
respath
[
2
]
==
"alive"
{
cmapErr
,
httpErr
=
ams
.
handleAlive
(
w
,
r
)
resvalid
=
true
}
case
4
:
if
respath
[
2
]
==
"clonemap"
&&
respath
[
3
]
==
"mas"
{
...
...
@@ -160,6 +163,17 @@ func (ams *AMS) handleAPI(w http.ResponseWriter, r *http.Request) {
}
}
// handleAlive is the handler for requests to path /api/alive
func
(
ams
*
AMS
)
handleAlive
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
cmapErr
,
httpErr
error
)
{
if
r
.
Method
==
"GET"
{
httpErr
=
httpreply
.
Alive
(
w
,
nil
)
}
else
{
httpErr
=
httpreply
.
MethodNotAllowed
(
w
)
cmapErr
=
errors
.
New
(
"Error: Method not allowed on path /api/alive"
)
}
return
}
// handleCloneMAP is the handler for requests to path /api/clonemap
func
(
ams
*
AMS
)
handleCloneMAP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
cmapErr
,
httpErr
error
)
{
if
r
.
Method
==
"GET"
{
...
...
pkg/ams/kube.go
View file @
5f99fa19
...
...
@@ -252,7 +252,7 @@ func (kube *kubeDeployment) createHeadlessService(masID int) (err error) {
"app"
:
"mas"
+
strconv
.
Itoa
(
masID
)
+
"agencies"
,
},
Ports
:
[]
apicorev1
.
ServicePort
{
apicorev1
.
ServicePort
{
{
Port
:
10000
,
Name
:
"mas"
+
strconv
.
Itoa
(
masID
)
+
"agencies"
,
},
...
...
@@ -271,30 +271,30 @@ func (kube *kubeDeployment) createStatefulSet(masID int, imID int, image string,
// Pod Spec
podSpec
:=
apicorev1
.
PodSpec
{
Containers
:
[]
apicorev1
.
Container
{
apicorev1
.
Container
{
{
Name
:
"mas"
+
strconv
.
Itoa
(
masID
)
+
"agencies"
,
Image
:
image
,
ImagePullPolicy
:
"Always"
,
Ports
:
[]
apicorev1
.
ContainerPort
{
apicorev1
.
ContainerPort
{
{
ContainerPort
:
10000
,
Name
:
"mas"
+
strconv
.
Itoa
(
masID
)
+
"agencies"
,
},
},
Env
:
[]
apicorev1
.
EnvVar
{
apicorev1
.
EnvVar
{
{
Name
:
"CLONEMAP_LOGGING"
,
Value
:
loggingEnv
,
},
apicorev1
.
EnvVar
{
{
Name
:
"CLONEMAP_MQTT"
,
Value
:
mqttEnv
,
},
apicorev1
.
EnvVar
{
{
Name
:
"CLONEMAP_DF"
,
Value
:
dfEnv
,
},
apicorev1
.
EnvVar
{
{
Name
:
"CLONEMAP_LOG_LEVEL"
,
Value
:
os
.
Getenv
(
"CLONEMAP_LOG_LEVEL"
),
},
...
...
@@ -343,7 +343,7 @@ func (kube *kubeDeployment) createStatefulSet(masID int, imID int, image string,
}
if
pullSecret
!=
""
{
podSpec
.
ImagePullSecrets
=
[]
apicorev1
.
LocalObjectReference
{
apicorev1
.
LocalObjectReference
{
{
Name
:
pullSecret
,
},
}
...
...
pkg/common/httpreply/httpreply.go
View file @
5f99fa19
...
...
@@ -112,6 +112,18 @@ func Resource(w http.ResponseWriter, v interface{}, cmaperr error) (err error) {
return
}
// Alive is standard response for liveness probe
func
Alive
(
w
http
.
ResponseWriter
,
cmaperr
error
)
(
err
error
)
{
if
cmaperr
==
nil
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"text/plain"
)
w
.
WriteHeader
(
http
.
StatusOK
)
_
,
err
=
w
.
Write
([]
byte
(
"I am alive"
))
}
else
{
err
=
CMAPError
(
w
,
cmaperr
.
Error
())
}
return
}
// JSONMarshalError writes standard response for JSON Marshal Error
func
JSONMarshalError
(
w
http
.
ResponseWriter
)
(
err
error
)
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"text/plain"
)
...
...
pkg/df/client/client.go
View file @
5f99fa19
...
...
@@ -69,6 +69,17 @@ var httpClient = &http.Client{Timeout: time.Second * 60}
var
delay
=
time
.
Second
*
1
var
numRetries
=
4
// Alive tests if alive
func
Alive
()
(
alive
bool
)
{
alive
=
false
_
,
httpStatus
,
err
:=
httpretry
.
Get
(
httpClient
,
"http://"
+
Host
+
":"
+
strconv
.
Itoa
(
Port
)
+
"/api/alive"
,
time
.
Second
*
2
,
2
)
if
err
==
nil
&&
httpStatus
==
http
.
StatusOK
{
alive
=
true
}
return
}
// PostSvc post an mas
func
PostSvc
(
masID
int
,
svc
schemas
.
Service
)
(
retSvc
schemas
.
Service
,
httpStatus
int
,
err
error
)
{
var
body
[]
byte
...
...
@@ -123,6 +134,18 @@ func PostGraph(masID int, gr schemas.Graph) (httpStatus int, err error) {
return
}
// GetGraph returns graph of mas
func
GetGraph
(
masID
int
)
(
graph
schemas
.
Graph
,
httpStatus
int
,
err
error
)
{
var
body
[]
byte
body
,
httpStatus
,
err
=
httpretry
.
Get
(
httpClient
,
"http://"
+
Host
+
":"
+
strconv
.
Itoa
(
Port
)
+
"/api/df/"
+
strconv
.
Itoa
(
masID
)
+
"/graph"
,
time
.
Second
*
2
,
2
)
if
err
!=
nil
{
return
}
err
=
json
.
Unmarshal
(
body
,
&
graph
)
return
}
// Init initializes the client
func
Init
(
timeout
time
.
Duration
,
del
time
.
Duration
,
numRet
int
)
{
httpClient
.
Timeout
=
timeout
...
...
pkg/df/handler.go
View file @
5f99fa19
...
...
@@ -65,6 +65,11 @@ func (df *DF) handleAPI(w http.ResponseWriter, r *http.Request) {
resvalid
:=
false
switch
len
(
respath
)
{
case
3
:
if
respath
[
2
]
==
"alive"
{
cmapErr
,
httpErr
=
df
.
handleAlive
(
w
,
r
)
resvalid
=
true
}
case
5
:
var
masID
int
masID
,
cmapErr
=
strconv
.
Atoi
(
respath
[
3
])
...
...
@@ -124,6 +129,17 @@ func (df *DF) handleAPI(w http.ResponseWriter, r *http.Request) {
}
}
// handleAlive is the handler for requests to path /api/alive
func
(
df
*
DF
)
handleAlive
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
cmapErr
,
httpErr
error
)
{
if
r
.
Method
==
"GET"
{
httpErr
=
httpreply
.
Alive
(
w
,
nil
)
}
else
{
httpErr
=
httpreply
.
MethodNotAllowed
(
w
)
cmapErr
=
errors
.
New
(
"Error: Method not allowed on path /api/alive"
)
}
return
}
// handlemasID is the handler for requests to path /api/df/{mas-id}/svc
func
(
df
*
DF
)
handlemasID
(
masID
int
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
cmapErr
,
httpErr
error
)
{
...
...
pkg/frontend/platform.go
View file @
5f99fa19
...
...
@@ -47,6 +47,12 @@ package frontend
import
(
"errors"
"net/http"
amsclient
"git.rwth-aachen.de/acs/public/cloud/mas/clonemap/pkg/ams/client"
"git.rwth-aachen.de/acs/public/cloud/mas/clonemap/pkg/common/httpreply"
dfclient
"git.rwth-aachen.de/acs/public/cloud/mas/clonemap/pkg/df/client"
logclient
"git.rwth-aachen.de/acs/public/cloud/mas/clonemap/pkg/logger/client"
"git.rwth-aachen.de/acs/public/cloud/mas/clonemap/pkg/schemas"
)
// handlePlatform handles requests to /api/pf/...
...
...
@@ -56,6 +62,7 @@ func (fe *Frontend) handlePlatform(w http.ResponseWriter, r *http.Request,
switch
len
(
respath
)
{
case
4
:
if
respath
[
3
]
==
"modules"
{
cmapErr
,
httpErr
=
fe
.
handleModules
(
w
,
r
)
resvalid
=
true
}
default
:
...
...
@@ -63,3 +70,29 @@ func (fe *Frontend) handlePlatform(w http.ResponseWriter, r *http.Request,
}
return
}
// handleModules is the handler for requests to path /api/pf/modules
func
(
fe
*
Frontend
)
handleModules
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
cmapErr
,
httpErr
error
)
{
if
r
.
Method
==
"GET"
{
// return short info of all MAS
var
mods
schemas
.
ModuleStatus
mods
,
cmapErr
=
getModuleStatus
()
if
cmapErr
==
nil
{
httpErr
=
httpreply
.
Resource
(
w
,
mods
,
cmapErr
)
}
else
{
httpErr
=
httpreply
.
CMAPError
(
w
,
cmapErr
.
Error
())
}
}
else
{
httpErr
=
httpreply
.
MethodNotAllowed
(
w
)
cmapErr
=
errors
.
New
(
"Error: Method not allowed on path /api/pf/modules"
)
}
return
}
// getModuleStatus returns the on/off status of all modules
func
getModuleStatus
()
(
mods
schemas
.
ModuleStatus
,
err
error
)
{
mods
.
Logging
=
logclient
.
Alive
()
mods
.
Core
=
amsclient
.
Alive
()
mods
.
DF
=
dfclient
.
Alive
()
return
}
pkg/logger/client/client.go
View file @
5f99fa19
...
...
@@ -65,6 +65,17 @@ var httpClient = &http.Client{Timeout: time.Second * 60}
var
delay
=
time
.
Second
*
1
var
numRetries
=
4
// Alive tests if alive
func
Alive
()
(
alive
bool
)
{
alive
=
false
_
,
httpStatus
,
err
:=
httpretry
.
Get
(
httpClient
,
"http://"
+
Host
+
":"
+
strconv
.
Itoa
(
Port
)
+
"/api/alive"
,
time
.
Second
*
2
,
2
)
if
err
==
nil
&&
httpStatus
==
http
.
StatusOK
{
alive
=
true
}
return
}
// PostLogs posts new log messages to logger
func
PostLogs
(
masID
int
,
logs
[]
schemas
.
LogMessage
)
(
httpStatus
int
,
err
error
)
{
js
,
_
:=
json
.
Marshal
(
logs
)
...
...
@@ -73,6 +84,23 @@ func PostLogs(masID int, logs []schemas.LogMessage) (httpStatus int, err error)
return
}
// GetLatestLogs gets log messages
func
GetLatestLogs
(
masID
int
,
agentID
int
,
topic
string
,
num
int
)
(
msgs
[]
schemas
.
LogMessage
,
httpStatus
int
,
err
error
)
{
var
body
[]
byte
body
,
httpStatus
,
err
=
httpretry
.
Get
(
httpClient
,
"http://"
+
Host
+
":"
+
strconv
.
Itoa
(
Port
)
+
"/api/logging/"
+
strconv
.
Itoa
(
masID
)
+
"/"
+
strconv
.
Itoa
(
agentID
)
+
"/"
+
topic
+
"/latest/"
+
strconv
.
Itoa
(
num
),
time
.
Second
*
2
,
4
)
if
err
!=
nil
{
return
}
err
=
json
.
Unmarshal
(
body
,
&
msgs
)
if
err
!=
nil
{
msgs
=
[]
schemas
.
LogMessage
{}
}
return
}
// PutState updates the state
func
PutState
(
state
schemas
.
State
)
(
httpStatus
int
,
err
error
)
{
js
,
_
:=
json
.
Marshal
(
state
)
...
...
pkg/logger/handler.go
View file @
5f99fa19
...
...
@@ -68,6 +68,11 @@ func (logger *Logger) handleAPI(w http.ResponseWriter, r *http.Request) {
resvalid
:=
false
switch
len
(
respath
)
{
case
3
:
if
respath
[
2
]
==
"alive"
{
cmapErr
,
httpErr
=
logger
.
handleAlive
(
w
,
r
)
resvalid
=
true
}
case
5
:
if
respath
[
2
]
==
"logging"
{
var
masID
int
...
...
@@ -162,6 +167,17 @@ func (logger *Logger) handleAPI(w http.ResponseWriter, r *http.Request) {
}
}
// handleAlive is the handler for requests to path /api/alive
func
(
logger
*
Logger
)
handleAlive
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
cmapErr
,
httpErr
error
)
{
if
r
.
Method
==
"GET"
{
httpErr
=
httpreply
.
Alive
(
w
,
nil
)
}
else
{
httpErr
=
httpreply
.
MethodNotAllowed
(
w
)
cmapErr
=
errors
.
New
(
"Error: Method not allowed on path /api/alive"
)
}
return
}
// handleLoggerNew is the handler for requests to path /api/logger/{mas-id}/{agent-id}/{logtype}
func
(
logger
*
Logger
)
handleLoggerNew
(
masID
int
,
agentid
int
,
logType
string
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
cmapErr
,
httpErr
error
)
{
...
...
pkg/schemas/core.go
View file @
5f99fa19
...
...
@@ -56,13 +56,20 @@ type CloneMAP struct {
Uptime
time
.
Time
`json:"uptime,omitempty"`
// uptime of clonemap instance
}
// ModuleStatus shows the status of clonemaps modules
type
ModuleStatus
struct
{
Core
bool
`json:"core"`
// Core module
DF
bool
`json:"df"`
// DF module
Logging
bool
`json:"logging"`
// Logging module
}
// MASInfoShort contains info about MAS spec, agents in MAS
type
MASInfoShort
struct
{
ID
int
`json:"id"`
Config
MASConfig
`json:"config"`
NumAgents
int
`json:"numags"`
Uptime
time
.
Time
`json:"uptime"`
Status
Status
`json:"status"`
ID
int
`json:"id"`
Config
MASConfig
`json:"config"`
NumAgents
int
`json:"numags"`
Uptime
time
.
Time
`json:"uptime"`
Status
Status
`json:"status"`
}
// MASInfo contains info about MAS spec, agents and agencies in MAS
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment