mirror of https://github.com/k3s-io/k3s
267 lines
6.7 KiB
Go
267 lines
6.7 KiB
Go
/*
|
|
Copyright 2015 The Kubernetes Authors All rights reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package mesos
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
log "github.com/golang/glog"
|
|
"github.com/mesos/mesos-go/detector"
|
|
"github.com/mesos/mesos-go/mesosutil"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
// Test data
|
|
|
|
const (
|
|
TEST_MASTER_ID = "master-12345"
|
|
TEST_MASTER_IP = 177048842 // 10.141.141.10
|
|
TEST_MASTER_PORT = 5050
|
|
|
|
TEST_STATE_JSON = `
|
|
{
|
|
"version": "0.22.0",
|
|
"unregistered_frameworks": [],
|
|
"started_tasks": 0,
|
|
"start_time": 1429456501.61141,
|
|
"staged_tasks": 0,
|
|
"slaves": [
|
|
{
|
|
"resources": {
|
|
"ports": "[31000-32000]",
|
|
"mem": 15360,
|
|
"disk": 470842,
|
|
"cpus": 8
|
|
},
|
|
"registered_time": 1429456502.46999,
|
|
"pid": "slave(1)@mesos1.internal.company.com:5050",
|
|
"id": "20150419-081501-16777343-5050-16383-S2",
|
|
"hostname": "mesos1.internal.company.com",
|
|
"attributes": {},
|
|
"active": true
|
|
},
|
|
{
|
|
"resources": {
|
|
"ports": "[31000-32000]",
|
|
"mem": 15360,
|
|
"disk": 470842,
|
|
"cpus": 8
|
|
},
|
|
"registered_time": 1429456502.4144,
|
|
"pid": "slave(1)@mesos2.internal.company.com:5050",
|
|
"id": "20150419-081501-16777343-5050-16383-S1",
|
|
"hostname": "mesos2.internal.company.com",
|
|
"attributes": {},
|
|
"active": true
|
|
},
|
|
{
|
|
"resources": {
|
|
"ports": "[31000-32000]",
|
|
"mem": 15360,
|
|
"disk": 470842,
|
|
"cpus": 8
|
|
},
|
|
"registered_time": 1429456502.02879,
|
|
"pid": "slave(1)@mesos3.internal.company.com:5050",
|
|
"id": "20150419-081501-16777343-5050-16383-S0",
|
|
"hostname": "mesos3.internal.company.com",
|
|
"attributes": {},
|
|
"active": true
|
|
}
|
|
],
|
|
"pid": "master@mesos-master0.internal.company.com:5050",
|
|
"orphan_tasks": [],
|
|
"lost_tasks": 0,
|
|
"leader": "master@mesos-master0.internal.company.com:5050",
|
|
"killed_tasks": 0,
|
|
"failed_tasks": 0,
|
|
"elected_time": 1429456501.61638,
|
|
"deactivated_slaves": 0,
|
|
"completed_frameworks": [],
|
|
"build_user": "buildbot",
|
|
"build_time": 1425085311,
|
|
"build_date": "2015-02-27 17:01:51",
|
|
"activated_slaves": 3,
|
|
"finished_tasks": 0,
|
|
"flags": {
|
|
"zk_session_timeout": "10secs",
|
|
"work_dir": "/tmp/mesos/local/Lc9arz",
|
|
"webui_dir": "/usr/local/share/mesos/webui",
|
|
"version": "false",
|
|
"user_sorter": "drf",
|
|
"slave_reregister_timeout": "10mins",
|
|
"logbufsecs": "0",
|
|
"log_auto_initialize": "true",
|
|
"initialize_driver_logging": "true",
|
|
"framework_sorter": "drf",
|
|
"authenticators": "crammd5",
|
|
"authenticate_slaves": "false",
|
|
"authenticate": "false",
|
|
"allocation_interval": "1secs",
|
|
"logging_level": "INFO",
|
|
"quiet": "false",
|
|
"recovery_slave_removal_limit": "100%",
|
|
"registry": "replicated_log",
|
|
"registry_fetch_timeout": "1mins",
|
|
"registry_store_timeout": "5secs",
|
|
"registry_strict": "false",
|
|
"root_submissions": "true"
|
|
},
|
|
"frameworks": [],
|
|
"git_branch": "refs/heads/0.22.0-rc1",
|
|
"git_sha": "46834faca67f877631e1beb7d61be5c080ec3dc2",
|
|
"git_tag": "0.22.0-rc1",
|
|
"hostname": "localhost",
|
|
"id": "20150419-081501-16777343-5050-16383"
|
|
}`
|
|
)
|
|
|
|
// Mocks
|
|
|
|
type FakeMasterDetector struct {
|
|
callback detector.MasterChanged
|
|
done chan struct{}
|
|
}
|
|
|
|
func newFakeMasterDetector() *FakeMasterDetector {
|
|
return &FakeMasterDetector{
|
|
done: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
func (md FakeMasterDetector) Cancel() {
|
|
close(md.done)
|
|
}
|
|
|
|
func (md FakeMasterDetector) Detect(cb detector.MasterChanged) error {
|
|
md.callback = cb
|
|
leadingMaster := mesosutil.NewMasterInfo(TEST_MASTER_ID, TEST_MASTER_IP, TEST_MASTER_PORT)
|
|
cb.OnMasterChanged(leadingMaster)
|
|
return nil
|
|
}
|
|
|
|
func (md FakeMasterDetector) Done() <-chan struct{} {
|
|
return md.done
|
|
}
|
|
|
|
// Auxilliary functions
|
|
|
|
func makeHttpMocks() (*httptest.Server, *http.Client, *http.Transport) {
|
|
httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
log.V(4).Infof("Mocking response for HTTP request: %#v", r)
|
|
if r.URL.Path == "/state.json" {
|
|
w.WriteHeader(200) // OK
|
|
w.Header().Set("Content-Type", "application/json")
|
|
fmt.Fprintln(w, TEST_STATE_JSON)
|
|
} else {
|
|
w.WriteHeader(400)
|
|
fmt.Fprintln(w, "Bad Request")
|
|
}
|
|
}))
|
|
|
|
// Intercept all client requests and feed them to the test server
|
|
transport := &http.Transport{
|
|
Proxy: func(req *http.Request) (*url.URL, error) {
|
|
return url.Parse(httpServer.URL)
|
|
},
|
|
}
|
|
|
|
httpClient := &http.Client{Transport: transport}
|
|
|
|
return httpServer, httpClient, transport
|
|
}
|
|
|
|
// Tests
|
|
|
|
// test mesos.parseMesosState
|
|
func Test_parseMesosState(t *testing.T) {
|
|
state, err := parseMesosState([]byte(TEST_STATE_JSON))
|
|
|
|
if err != nil {
|
|
t.Fatalf("parseMesosState does not yield an error")
|
|
}
|
|
if state == nil {
|
|
t.Fatalf("parseMesosState yields a non-nil state")
|
|
}
|
|
if len(state.nodes) != 3 {
|
|
t.Fatalf("parseMesosState yields a state with 3 nodes")
|
|
}
|
|
}
|
|
|
|
// test mesos.listSlaves
|
|
func Test_listSlaves(t *testing.T) {
|
|
defer log.Flush()
|
|
md := FakeMasterDetector{}
|
|
httpServer, httpClient, httpTransport := makeHttpMocks()
|
|
defer httpServer.Close()
|
|
cacheTTL := 500 * time.Millisecond
|
|
mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL)
|
|
|
|
if err != nil {
|
|
t.Fatalf("createMesosClient does not yield an error")
|
|
}
|
|
|
|
slaveNodes, err := mesosClient.listSlaves(context.TODO())
|
|
|
|
if err != nil {
|
|
t.Fatalf("listSlaves does not yield an error")
|
|
}
|
|
if len(slaveNodes) != 3 {
|
|
t.Fatalf("listSlaves yields a collection of size 3")
|
|
}
|
|
|
|
expectedHostnames := map[string]struct{}{
|
|
"mesos1.internal.company.com": {},
|
|
"mesos2.internal.company.com": {},
|
|
"mesos3.internal.company.com": {},
|
|
}
|
|
|
|
actualHostnames := make(map[string]struct{})
|
|
for _, node := range slaveNodes {
|
|
actualHostnames[node.hostname] = struct{}{}
|
|
}
|
|
|
|
if !reflect.DeepEqual(expectedHostnames, actualHostnames) {
|
|
t.Fatalf("listSlaves yields a collection with the expected hostnames")
|
|
}
|
|
}
|
|
|
|
// test mesos.clusterName
|
|
func Test_clusterName(t *testing.T) {
|
|
defer log.Flush()
|
|
md := FakeMasterDetector{}
|
|
httpServer, httpClient, httpTransport := makeHttpMocks()
|
|
defer httpServer.Close()
|
|
cacheTTL := 500 * time.Millisecond
|
|
mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL)
|
|
|
|
name, err := mesosClient.clusterName(context.TODO())
|
|
|
|
if err != nil {
|
|
t.Fatalf("clusterName does not yield an error")
|
|
}
|
|
if name != defaultClusterName {
|
|
t.Fatalf("clusterName yields the expected (default) value")
|
|
}
|
|
}
|