introdcution of typesafe ids.
This commit is contained in:
parent
c86ea894d1
commit
556315906d
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"git.wamblee.org/converge/pkg/models"
|
||||
"git.wamblee.org/converge/pkg/server/matchmaker"
|
||||
"git.wamblee.org/converge/pkg/support/websocketutil"
|
||||
"log"
|
||||
@ -15,13 +16,13 @@ import (
|
||||
_ "time/tzdata"
|
||||
)
|
||||
|
||||
func parsePublicId(path string) (publicId string, _ error) {
|
||||
func parsePublicId(path string) (publicId models.RendezVousId, _ error) {
|
||||
pattern := regexp.MustCompile("/([^/]+)$")
|
||||
matches := pattern.FindStringSubmatch(path)
|
||||
if len(matches) != 2 {
|
||||
return "", fmt.Errorf("Invalid URL path '%s'", path)
|
||||
}
|
||||
return matches[1], nil
|
||||
return models.RendezVousId(matches[1]), nil
|
||||
}
|
||||
|
||||
func catchAllHandler(contextPath string) func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -14,14 +14,14 @@ const NAMESPACE = "converge"
|
||||
|
||||
// more efficient state representation for state
|
||||
type PrometheusState struct {
|
||||
agents map[string]*models.Agent
|
||||
clients map[string]*models.Client
|
||||
agents map[models.AgentGuid]*models.Agent
|
||||
clients map[models.ClientGuid]*models.Client
|
||||
}
|
||||
|
||||
func NewPrometheusState(state *models.State) *PrometheusState {
|
||||
res := PrometheusState{
|
||||
agents: make(map[string]*models.Agent),
|
||||
clients: make(map[string]*models.Client),
|
||||
agents: make(map[models.AgentGuid]*models.Agent),
|
||||
clients: make(map[models.ClientGuid]*models.Client),
|
||||
}
|
||||
for i, _ := range state.Agents {
|
||||
res.agents[state.Agents[i].Guid] = &state.Agents[i]
|
||||
@ -121,9 +121,9 @@ var (
|
||||
|
||||
func agentLabels(agent *models.Agent) prometheus.Labels {
|
||||
return prometheus.Labels{
|
||||
"agent_guid": agent.Guid,
|
||||
"agent_address": agent.RemoteAddr,
|
||||
"agent_id": agent.PublicId,
|
||||
"agent_guid": string(agent.Guid),
|
||||
"agent_address": string(agent.RemoteAddr),
|
||||
"agent_id": string(agent.PublicId),
|
||||
"agent_username": agent.EnvironmentInfo.Username,
|
||||
"agent_hostname": agent.EnvironmentInfo.Hostname,
|
||||
"agent_pwd": agent.EnvironmentInfo.Pwd,
|
||||
@ -134,12 +134,12 @@ func agentLabels(agent *models.Agent) prometheus.Labels {
|
||||
|
||||
func clientLabels(client *models.Client) prometheus.Labels {
|
||||
return prometheus.Labels{
|
||||
"client_guid": client.Guid,
|
||||
"client_address": client.RemoteAddr,
|
||||
"client_id": client.ClientId,
|
||||
"agent_id": client.PublicId,
|
||||
"agent_guid": client.AgentGuid,
|
||||
"client_sessiontype": client.SessionType,
|
||||
"client_guid": string(client.Guid),
|
||||
"client_address": string(client.RemoteAddr),
|
||||
"client_id": string(client.ClientId),
|
||||
"agent_id": string(client.PublicId),
|
||||
"agent_guid": string(client.AgentGuid),
|
||||
"client_sessiontype": string(client.SessionType),
|
||||
"client_username": client.EnvironmentInfo.Username,
|
||||
"client_hostname": client.EnvironmentInfo.Hostname,
|
||||
"client_pwd": client.EnvironmentInfo.Pwd,
|
||||
@ -154,11 +154,12 @@ func agentActive(agent *models.Agent) {
|
||||
removeAgentInfoMetrics(prevAgent)
|
||||
}
|
||||
agentInfo.With(agentLabels(agent)).Set(1)
|
||||
agentGuid := string(agent.Guid)
|
||||
agentStartTime.
|
||||
With(prometheus.Labels{"agent_guid": agent.Guid}).
|
||||
With(prometheus.Labels{"agent_guid": agentGuid}).
|
||||
Set(float64(agent.StartTime.UnixMilli()))
|
||||
agentDuration.
|
||||
With(prometheus.Labels{"agent_guid": agent.Guid}).
|
||||
With(prometheus.Labels{"agent_guid": agentGuid}).
|
||||
Set(float64(time.Now().Sub(agent.StartTime).Seconds()))
|
||||
}
|
||||
|
||||
@ -168,12 +169,12 @@ func clientActive(client *models.Client) {
|
||||
removeClientInfoMetrics(prevClient)
|
||||
}
|
||||
clientInfo.With(clientLabels(client)).Set(1)
|
||||
|
||||
clientGuid := string(client.Guid)
|
||||
clientStartTime.
|
||||
With(prometheus.Labels{"client_guid": client.Guid}).
|
||||
With(prometheus.Labels{"client_guid": clientGuid}).
|
||||
Set(float64(client.StartTime.UnixMilli()))
|
||||
clientDuration.
|
||||
With(prometheus.Labels{"client_guid": client.Guid}).
|
||||
With(prometheus.Labels{"client_guid": clientGuid}).
|
||||
Set(float64(time.Now().Sub(client.StartTime).Seconds()))
|
||||
}
|
||||
|
||||
@ -223,23 +224,23 @@ func updateMetrics(state *models.State) {
|
||||
func updateDurations() {
|
||||
for _, agent := range lastState.agents {
|
||||
agentDuration.
|
||||
With(prometheus.Labels{"agent_guid": agent.Guid}).
|
||||
With(prometheus.Labels{"agent_guid": string(agent.Guid)}).
|
||||
Set(float64(time.Now().Sub(agent.StartTime).Seconds()))
|
||||
}
|
||||
for _, client := range lastState.clients {
|
||||
clientDuration.
|
||||
With(prometheus.Labels{"client_guid": client.Guid}).
|
||||
With(prometheus.Labels{"client_guid": string(client.Guid)}).
|
||||
Set(float64(time.Now().Sub(client.StartTime).Seconds()))
|
||||
}
|
||||
}
|
||||
|
||||
func updateMetricsImpl(state *PrometheusState) {
|
||||
|
||||
agentGuids := make(map[string]*models.Agent)
|
||||
clientGuids := make(map[string]*models.Client)
|
||||
agentGuids := make(map[models.AgentGuid]*models.Agent)
|
||||
clientGuids := make(map[models.ClientGuid]*models.Client)
|
||||
|
||||
agentCount.Set(float64(len(state.agents)))
|
||||
disconnectedAgents := make(map[string]*models.Agent)
|
||||
disconnectedAgents := make(map[models.AgentGuid]*models.Agent)
|
||||
for _, agent := range lastState.agents {
|
||||
disconnectedAgents[agent.Guid] = agent
|
||||
}
|
||||
@ -258,7 +259,7 @@ func updateMetricsImpl(state *PrometheusState) {
|
||||
clientCount.Set(float64(len(state.clients)))
|
||||
|
||||
// with this app
|
||||
disconnectedClients := make(map[string]*models.Client)
|
||||
disconnectedClients := make(map[models.ClientGuid]*models.Client)
|
||||
for _, client := range lastState.clients {
|
||||
disconnectedClients[client.Guid] = client
|
||||
}
|
||||
@ -283,7 +284,7 @@ func removeAgentInfoMetrics(agent *models.Agent) bool {
|
||||
|
||||
func removeAgentMetrics(agent *models.Agent) {
|
||||
ok1 := removeAgentInfoMetrics(agent)
|
||||
guidLabels := prometheus.Labels{"agent_guid": agent.Guid}
|
||||
guidLabels := prometheus.Labels{"agent_guid": string(agent.Guid)}
|
||||
ok2 := agentStartTime.Delete(guidLabels)
|
||||
// delayed deletion of the duration sow we are sure the prometheus has the last data.
|
||||
go func() {
|
||||
@ -305,7 +306,7 @@ func removeClientInfoMetrics(client *models.Client) bool {
|
||||
|
||||
func removeClientMetrics(client *models.Client) {
|
||||
ok1 := removeClientInfoMetrics(client)
|
||||
guidLabels := prometheus.Labels{"client_guid": client.Guid}
|
||||
guidLabels := prometheus.Labels{"client_guid": string(client.Guid)}
|
||||
ok2 := clientStartTime.Delete(guidLabels)
|
||||
// delayed deletion of the duration sow we are sure the prometheus has the last data.
|
||||
go func() {
|
||||
|
@ -81,7 +81,7 @@ func main() {
|
||||
|
||||
state := models.State{}
|
||||
agent := models.Agent{
|
||||
Guid: strconv.Itoa(rand.Int()),
|
||||
Guid: models.AgentGuid(strconv.Itoa(rand.Int())),
|
||||
RemoteAddr: "10.220.1.3:3333",
|
||||
PublicId: "id",
|
||||
StartTime: time.Now().In(japan),
|
||||
@ -96,13 +96,13 @@ func main() {
|
||||
}
|
||||
state.Agents = append(state.Agents, agent)
|
||||
client := models.Client{
|
||||
Guid: strconv.Itoa(rand.Int()),
|
||||
RemoteAddr: "10.1.3.3",
|
||||
PublicId: "c1",
|
||||
AgentGuid: "12342342",
|
||||
ClientId: "3",
|
||||
Guid: models.ClientGuid(strconv.Itoa(rand.Int())),
|
||||
RemoteAddr: models.RemoteAddr("10.1.3.3"),
|
||||
PublicId: models.RendezVousId("c1"),
|
||||
AgentGuid: models.AgentGuid("12342342"),
|
||||
ClientId: models.ClientId("3"),
|
||||
StartTime: time.Now().In(japan),
|
||||
SessionType: "sftp",
|
||||
SessionType: models.SessionType("sftp"),
|
||||
}
|
||||
state.Clients = append(state.Clients, client)
|
||||
return templates2.SessionsTab(&state, netherlands)
|
||||
|
@ -1,18 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.wamblee.org/converge/pkg/comms"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Agent struct {
|
||||
Guid string
|
||||
RemoteAddr string
|
||||
PublicId string
|
||||
StartTime time.Time
|
||||
|
||||
// TODO add remote address.
|
||||
|
||||
EnvironmentInfo comms.EnvironmentInfo
|
||||
ExpiryTime time.Time
|
||||
}
|
@ -1,17 +1 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.wamblee.org/converge/pkg/comms"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Guid string
|
||||
RemoteAddr string
|
||||
PublicId string
|
||||
ClientId string
|
||||
AgentGuid string
|
||||
StartTime time.Time
|
||||
SessionType string
|
||||
EnvironmentInfo comms.EnvironmentInfo
|
||||
}
|
||||
|
@ -1,5 +1,40 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.wamblee.org/converge/pkg/comms"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RendezVousId string
|
||||
type AgentGuid string
|
||||
type ClientGuid string
|
||||
type ClientId string
|
||||
type SessionType string
|
||||
type RemoteAddr string
|
||||
|
||||
type Agent struct {
|
||||
Guid AgentGuid
|
||||
RemoteAddr RemoteAddr
|
||||
PublicId RendezVousId
|
||||
StartTime time.Time
|
||||
|
||||
// TODO add remote address.
|
||||
|
||||
EnvironmentInfo comms.EnvironmentInfo
|
||||
ExpiryTime time.Time
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Guid ClientGuid
|
||||
RemoteAddr RemoteAddr
|
||||
PublicId RendezVousId
|
||||
ClientId ClientId
|
||||
AgentGuid AgentGuid
|
||||
StartTime time.Time
|
||||
SessionType SessionType
|
||||
EnvironmentInfo comms.EnvironmentInfo
|
||||
}
|
||||
|
||||
// State is a description of the current state of converge.
|
||||
// Created by the server and used for updating the web client
|
||||
// and prometheus metrics.
|
||||
|
@ -30,11 +30,11 @@ type ClientConnection struct {
|
||||
clientConnection iowrappers2.ReadWriteAddrCloser
|
||||
}
|
||||
|
||||
func newAgent(commChannel comms.CommChannel, publicId string, agentInfo comms.EnvironmentInfo) *agentConnection {
|
||||
func newAgent(commChannel comms.CommChannel, publicId models.RendezVousId, agentInfo comms.EnvironmentInfo) *agentConnection {
|
||||
return &agentConnection{
|
||||
Agent: models.Agent{
|
||||
Guid: strconv.Itoa(rand.Int()),
|
||||
RemoteAddr: commChannel.Session.RemoteAddr().String(),
|
||||
Guid: models.AgentGuid(strconv.Itoa(rand.Int())),
|
||||
RemoteAddr: models.RemoteAddr(commChannel.Session.RemoteAddr().String()),
|
||||
PublicId: publicId,
|
||||
StartTime: time.Now(),
|
||||
EnvironmentInfo: agentInfo,
|
||||
@ -43,15 +43,15 @@ func newAgent(commChannel comms.CommChannel, publicId string, agentInfo comms.En
|
||||
}
|
||||
}
|
||||
|
||||
func newClient(publicId string, clientConn iowrappers2.ReadWriteAddrCloser,
|
||||
agentConn net.Conn, agentGuid string) *ClientConnection {
|
||||
func newClient(publicId models.RendezVousId, clientConn iowrappers2.ReadWriteAddrCloser,
|
||||
agentConn net.Conn, agentGuid models.AgentGuid) *ClientConnection {
|
||||
return &ClientConnection{
|
||||
Client: models.Client{
|
||||
Guid: strconv.Itoa(rand.Int()),
|
||||
RemoteAddr: clientConn.RemoteAddr().String(),
|
||||
Guid: models.ClientGuid(strconv.Itoa(rand.Int())),
|
||||
RemoteAddr: models.RemoteAddr(clientConn.RemoteAddr().String()),
|
||||
PublicId: publicId,
|
||||
AgentGuid: agentGuid,
|
||||
ClientId: strconv.Itoa(clientIdGenerator.IncrementAndGet()),
|
||||
ClientId: models.ClientId(strconv.Itoa(clientIdGenerator.IncrementAndGet())),
|
||||
StartTime: time.Now(),
|
||||
},
|
||||
agentConnection: agentConn,
|
||||
@ -66,14 +66,14 @@ func (match *ClientConnection) Synchronize() {
|
||||
type Admin struct {
|
||||
// map of public id to agent
|
||||
mutex sync.Mutex
|
||||
agents map[string]*agentConnection
|
||||
agents map[models.RendezVousId]*agentConnection
|
||||
clients []*ClientConnection
|
||||
}
|
||||
|
||||
func NewAdmin() *Admin {
|
||||
return &Admin{
|
||||
mutex: sync.Mutex{},
|
||||
agents: make(map[string]*agentConnection),
|
||||
agents: make(map[models.RendezVousId]*agentConnection),
|
||||
clients: make([]*ClientConnection, 0), // not strictly needed
|
||||
}
|
||||
}
|
||||
@ -93,8 +93,8 @@ func (admin *Admin) CreateNotifification() *models.State {
|
||||
return &state
|
||||
}
|
||||
|
||||
func (admin *Admin) getFreeId(publicId string) (string, error) {
|
||||
usedIds := make(map[string]bool)
|
||||
func (admin *Admin) getFreeId(publicId models.RendezVousId) (models.RendezVousId, error) {
|
||||
usedIds := make(map[models.RendezVousId]bool)
|
||||
for _, agent := range admin.agents {
|
||||
usedIds[agent.PublicId] = true
|
||||
}
|
||||
@ -103,16 +103,16 @@ func (admin *Admin) getFreeId(publicId string) (string, error) {
|
||||
}
|
||||
if usedIds[publicId] {
|
||||
for i := 0; i < 100; i++ {
|
||||
candidate := publicId + "-" + strconv.Itoa(i)
|
||||
if !usedIds[candidate] {
|
||||
return candidate, nil
|
||||
candidate := string(publicId) + "-" + strconv.Itoa(i)
|
||||
if !usedIds[models.RendezVousId(candidate)] {
|
||||
return models.RendezVousId(candidate), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("Could not allocate agent id based on requested public id '%s'", publicId)
|
||||
}
|
||||
|
||||
func (admin *Admin) AddAgent(publicId string, agentInfo comms.EnvironmentInfo, conn io.ReadWriteCloser) (*agentConnection, error) {
|
||||
func (admin *Admin) AddAgent(publicId models.RendezVousId, agentInfo comms.EnvironmentInfo, conn io.ReadWriteCloser) (*agentConnection, error) {
|
||||
admin.mutex.Lock()
|
||||
defer admin.mutex.Unlock()
|
||||
|
||||
@ -126,7 +126,7 @@ func (admin *Admin) AddAgent(publicId string, agentInfo comms.EnvironmentInfo, c
|
||||
comms.SendRegistrationMessage(conn, comms.AgentRegistration{
|
||||
Ok: true,
|
||||
Message: message,
|
||||
Id: publicId,
|
||||
Id: string(publicId),
|
||||
})
|
||||
} else {
|
||||
comms.SendRegistrationMessage(conn, comms.AgentRegistration{
|
||||
@ -149,7 +149,7 @@ func (admin *Admin) AddAgent(publicId string, agentInfo comms.EnvironmentInfo, c
|
||||
return agent, nil
|
||||
}
|
||||
|
||||
func (admin *Admin) AddClient(publicId string, clientConn iowrappers2.ReadWriteAddrCloser) (*ClientConnection, error) {
|
||||
func (admin *Admin) AddClient(publicId models.RendezVousId, clientConn iowrappers2.ReadWriteAddrCloser) (*ClientConnection, error) {
|
||||
admin.mutex.Lock()
|
||||
defer admin.mutex.Unlock()
|
||||
|
||||
@ -172,7 +172,7 @@ func (admin *Admin) AddClient(publicId string, clientConn iowrappers2.ReadWriteA
|
||||
// Before using this connection for SSH we use it to send client metadata to the
|
||||
// agent
|
||||
err = comms.SendClientInfo(agentConn, comms.ClientInfo{
|
||||
ClientId: client.ClientId,
|
||||
ClientId: string(client.ClientId),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -194,7 +194,7 @@ func (admin *Admin) getAgentConnection(agent *agentConnection) (net.Conn, error)
|
||||
return agentConn, err
|
||||
}
|
||||
|
||||
func (admin *Admin) RemoveAgent(publicId string) error {
|
||||
func (admin *Admin) RemoveAgent(publicId models.RendezVousId) error {
|
||||
admin.mutex.Lock()
|
||||
defer admin.mutex.Unlock()
|
||||
|
||||
@ -230,7 +230,7 @@ func (admin *Admin) RemoveClient(client *ClientConnection) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (admin *Admin) SetSessionType(clientId string, sessionType string) {
|
||||
func (admin *Admin) SetSessionType(clientId models.ClientId, sessionType models.SessionType) {
|
||||
admin.mutex.Lock()
|
||||
defer admin.mutex.Unlock()
|
||||
for _, client := range admin.clients {
|
||||
|
@ -25,7 +25,7 @@ func NewMatchMaker(notifier Notifier) *MatchMaker {
|
||||
return &converge
|
||||
}
|
||||
|
||||
func (converge *MatchMaker) Register(publicId string, conn io.ReadWriteCloser) error {
|
||||
func (converge *MatchMaker) Register(publicId models.RendezVousId, conn io.ReadWriteCloser) error {
|
||||
|
||||
serverInfo := comms.ServerInfo{}
|
||||
|
||||
@ -53,7 +53,7 @@ func (converge *MatchMaker) Register(publicId string, conn io.ReadWriteCloser) e
|
||||
},
|
||||
func(session comms.SessionInfo) {
|
||||
log.Println("Recceived sessioninfo ", session)
|
||||
converge.admin.SetSessionType(session.ClientId, session.SessionType)
|
||||
converge.admin.SetSessionType(models.ClientId(session.ClientId), models.SessionType(session.SessionType))
|
||||
},
|
||||
func(expiry comms.ExpiryTimeUpdate) {
|
||||
agent.ExpiryTime = expiry.ExpiryTime
|
||||
@ -68,7 +68,7 @@ func (converge *MatchMaker) Register(publicId string, conn io.ReadWriteCloser) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (converge *MatchMaker) Connect(wsProxyMode bool, publicId string, conn iowrappers2.ReadWriteAddrCloser) error {
|
||||
func (converge *MatchMaker) Connect(wsProxyMode bool, publicId models.RendezVousId, conn iowrappers2.ReadWriteAddrCloser) error {
|
||||
defer conn.Close()
|
||||
|
||||
log.Printf("Using wsproxy protocol %v", wsProxyMode)
|
||||
|
@ -48,7 +48,7 @@ templ State(state *models.State, location *time.Location) {
|
||||
</thead>
|
||||
for _, agent := range state.Agents {
|
||||
<tr>
|
||||
<td>{agent.PublicId}</td>
|
||||
<td>{string(agent.PublicId)}</td>
|
||||
<td>{agent.StartTime.In(location).Format(time.DateTime)}</td>
|
||||
<td>{agent.ExpiryTime.In(location).Format(time.DateTime)}</td>
|
||||
<td>{agent.EnvironmentInfo.Username}</td>
|
||||
@ -82,10 +82,10 @@ templ State(state *models.State, location *time.Location) {
|
||||
</thead>
|
||||
for _, client := range state.Clients {
|
||||
<tr>
|
||||
<td>{client.ClientId}</td>
|
||||
<td>{string(client.ClientId)}</td>
|
||||
<td>{client.StartTime.In(location).Format(time.DateTime)}</td>
|
||||
<td>{client.SessionType}</td>
|
||||
<td>{client.PublicId}</td>
|
||||
<td>{string(client.SessionType)}</td>
|
||||
<td>{string(client.PublicId)}</td>
|
||||
<td>{client.EnvironmentInfo.Username}</td>
|
||||
<td>{client.EnvironmentInfo.Hostname}</td>
|
||||
<td>{client.EnvironmentInfo.OS}</td>
|
||||
|
Loading…
Reference in New Issue
Block a user