summaryrefslogtreecommitdiffstats
path: root/model
diff options
context:
space:
mode:
authorCorey Hulen <corey@hulen.com>2016-08-04 09:25:37 -0800
committerHarrison Healey <harrisonmhealey@gmail.com>2016-08-04 13:25:37 -0400
commit59d971dc751b0414c5b38c9df4b552e45f5641be (patch)
treed8c39aa5d1fa67d41d89bdd37f699a8e7ca7af36 /model
parentac90f5b38962c301318fff9118c4556537002941 (diff)
downloadchat-59d971dc751b0414c5b38c9df4b552e45f5641be.tar.gz
chat-59d971dc751b0414c5b38c9df4b552e45f5641be.tar.bz2
chat-59d971dc751b0414c5b38c9df4b552e45f5641be.zip
PLT-2899 adding clustering of app servers (#3682)
* PLT-2899 adding clustering of app servers * PLT-2899 base framework * PLT-2899 HA backend * PLT-2899 Fixing config file * PLT-2899 adding config syncing * PLT-2899 set System console to readonly when clustering enabled. * PLT-2899 Fixing publish API * PLT-2899 fixing strings
Diffstat (limited to 'model')
-rw-r--r--model/client.go10
-rw-r--r--model/cluster_info.go66
-rw-r--r--model/cluster_info_test.go32
-rw-r--r--model/config.go21
-rw-r--r--model/license.go6
5 files changed, 135 insertions, 0 deletions
diff --git a/model/client.go b/model/client.go
index b9a5d8830..3aff3c931 100644
--- a/model/client.go
+++ b/model/client.go
@@ -20,6 +20,7 @@ import (
const (
HEADER_REQUEST_ID = "X-Request-ID"
HEADER_VERSION_ID = "X-Version-ID"
+ HEADER_CLUSTER_ID = "X-Cluster-ID"
HEADER_ETAG_SERVER = "ETag"
HEADER_ETAG_CLIENT = "If-None-Match"
HEADER_FORWARDED = "X-Forwarded-For"
@@ -808,6 +809,15 @@ func (c *Client) GetLogs() (*Result, *AppError) {
}
}
+func (c *Client) GetClusterStatus() ([]*ClusterInfo, *AppError) {
+ if r, err := c.DoApiGet("/admin/cluster_status", "", ""); err != nil {
+ return nil, err
+ } else {
+ defer closeBody(r)
+ return ClusterInfosFromJson(r.Body), nil
+ }
+}
+
func (c *Client) GetAllAudits() (*Result, *AppError) {
if r, err := c.DoApiGet("/admin/audits", "", ""); err != nil {
return nil, err
diff --git a/model/cluster_info.go b/model/cluster_info.go
new file mode 100644
index 000000000..7c3384ae2
--- /dev/null
+++ b/model/cluster_info.go
@@ -0,0 +1,66 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "encoding/json"
+ "io"
+)
+
+type ClusterInfo struct {
+ Id string `json:"id"`
+ Version string `json:"version"`
+ ConfigHash string `json:"config_hash"`
+ InterNodeUrl string `json:"internode_url"`
+ Hostname string `json:"hostname"`
+ LastSuccessfulPing int64 `json:"last_ping"`
+ IsAlive bool `json:"is_alive"`
+}
+
+func (me *ClusterInfo) ToJson() string {
+ b, err := json.Marshal(me)
+ if err != nil {
+ return ""
+ } else {
+ return string(b)
+ }
+}
+
+func ClusterInfoFromJson(data io.Reader) *ClusterInfo {
+ decoder := json.NewDecoder(data)
+ var me ClusterInfo
+ err := decoder.Decode(&me)
+ if err == nil {
+ return &me
+ } else {
+ return nil
+ }
+}
+
+func (me *ClusterInfo) HaveEstablishedInitialContact() bool {
+ if me.Id != "" {
+ return true
+ }
+
+ return false
+}
+
+func ClusterInfosToJson(objmap []*ClusterInfo) string {
+ if b, err := json.Marshal(objmap); err != nil {
+ return ""
+ } else {
+ return string(b)
+ }
+}
+
+func ClusterInfosFromJson(data io.Reader) []*ClusterInfo {
+ decoder := json.NewDecoder(data)
+
+ var objmap []*ClusterInfo
+ if err := decoder.Decode(&objmap); err != nil {
+ return make([]*ClusterInfo, 0)
+ } else {
+ return objmap
+ }
+}
diff --git a/model/cluster_info_test.go b/model/cluster_info_test.go
new file mode 100644
index 000000000..d6348f5d1
--- /dev/null
+++ b/model/cluster_info_test.go
@@ -0,0 +1,32 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestClusterInfoJson(t *testing.T) {
+ cluster := ClusterInfo{Id: NewId(), InterNodeUrl: NewId(), Hostname: NewId()}
+ json := cluster.ToJson()
+ result := ClusterInfoFromJson(strings.NewReader(json))
+
+ if cluster.Id != result.Id {
+ t.Fatal("Ids do not match")
+ }
+}
+
+func TestClusterInfosJson(t *testing.T) {
+ cluster := ClusterInfo{Id: NewId(), InterNodeUrl: NewId(), Hostname: NewId()}
+ clusterInfos := make([]*ClusterInfo, 1)
+ clusterInfos[0] = &cluster
+ json := ClusterInfosToJson(clusterInfos)
+ result := ClusterInfosFromJson(strings.NewReader(json))
+
+ if clusterInfos[0].Id != result[0].Id {
+ t.Fatal("Ids do not match")
+ }
+
+}
diff --git a/model/config.go b/model/config.go
index b239c83ca..7fe575e58 100644
--- a/model/config.go
+++ b/model/config.go
@@ -80,6 +80,12 @@ type ServiceSettings struct {
RestrictCustomEmojiCreation *string
}
+type ClusterSettings struct {
+ Enable *bool
+ InterNodeListenAddress *string
+ InterNodeUrls []string
+}
+
type SSOSettings struct {
Enable bool
Secret string
@@ -297,6 +303,7 @@ type Config struct {
LocalizationSettings LocalizationSettings
SamlSettings SamlSettings
NativeAppSettings NativeAppSettings
+ ClusterSettings ClusterSettings
}
func (o *Config) ToJson() string {
@@ -707,6 +714,20 @@ func (o *Config) SetDefaults() {
*o.ServiceSettings.RestrictCustomEmojiCreation = RESTRICT_EMOJI_CREATION_ALL
}
+ if o.ClusterSettings.InterNodeListenAddress == nil {
+ o.ClusterSettings.InterNodeListenAddress = new(string)
+ *o.ClusterSettings.InterNodeListenAddress = ":8075"
+ }
+
+ if o.ClusterSettings.Enable == nil {
+ o.ClusterSettings.Enable = new(bool)
+ *o.ClusterSettings.Enable = false
+ }
+
+ if o.ClusterSettings.InterNodeUrls == nil {
+ o.ClusterSettings.InterNodeUrls = []string{}
+ }
+
if o.ComplianceSettings.Enable == nil {
o.ComplianceSettings.Enable = new(bool)
*o.ComplianceSettings.Enable = false
diff --git a/model/license.go b/model/license.go
index a60695890..a27b36263 100644
--- a/model/license.go
+++ b/model/license.go
@@ -38,6 +38,7 @@ type Features struct {
GoogleSSO *bool `json:"google_sso"`
Office365SSO *bool `json:"office365_sso"`
Compliance *bool `json:"compliance"`
+ Cluster *bool `json:"cluster"`
CustomBrand *bool `json:"custom_brand"`
MHPNS *bool `json:"mhpns"`
SAML *bool `json:"saml"`
@@ -81,6 +82,11 @@ func (f *Features) SetDefaults() {
*f.Compliance = *f.FutureFeatures
}
+ if f.Cluster == nil {
+ f.Cluster = new(bool)
+ *f.Cluster = *f.FutureFeatures
+ }
+
if f.CustomBrand == nil {
f.CustomBrand = new(bool)
*f.CustomBrand = *f.FutureFeatures