Skip to content

Commit f575607

Browse files
author
Gabriel Monroy
committed
add new packages
1 parent 08e8901 commit f575607

18 files changed

Lines changed: 1256 additions & 0 deletions

client/api.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package client
2+
3+
// Client interface used to interact with the cluster control plane
4+
type Client interface {
5+
Create(string, bool) error
6+
Destroy(string) error
7+
Start(string, bool) error
8+
Stop(string) error
9+
Scale(string, int) error
10+
List() error
11+
Status(string) error
12+
}

client/create.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package client
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/coreos/fleet/job"
8+
"github.com/coreos/fleet/unit"
9+
)
10+
11+
// Create schedules a new unit for the given component
12+
// and blocks until the unit is loaded
13+
func (c *FleetClient) Create(component string, data bool) (err error) {
14+
var (
15+
unitName string
16+
unitPtr *unit.Unit
17+
)
18+
// create unit
19+
if data == true {
20+
unitName, unitPtr, err = c.createDataUnit(component)
21+
} else {
22+
unitName, unitPtr, err = c.createServiceUnit(component)
23+
}
24+
if err != nil {
25+
return err
26+
}
27+
// schedule job
28+
j := job.NewJob(unitName, *unitPtr)
29+
if err := c.Fleet.CreateJob(j); err != nil {
30+
return fmt.Errorf("failed creating job %s: %v", unitName, err)
31+
}
32+
newState := job.JobStateLoaded
33+
err = c.Fleet.SetJobTargetState(unitName, newState)
34+
if err != nil {
35+
return err
36+
}
37+
errchan := waitForJobStates([]string{unitName}, testJobStateLoaded, 0, os.Stdout)
38+
for err := range errchan {
39+
return fmt.Errorf("error waiting for job %s: %v", unitName, err)
40+
}
41+
return nil
42+
}
43+
44+
// Create normal service unit
45+
func (c *FleetClient) createServiceUnit(component string) (unitName string, unitPtr *unit.Unit, err error) {
46+
num, err := c.nextUnit(component)
47+
if err != nil {
48+
return
49+
}
50+
unitName, err = formatUnitName(component, num)
51+
if err != nil {
52+
return
53+
}
54+
unitPtr, err = NewUnit(component)
55+
if err != nil {
56+
return
57+
}
58+
return unitName, unitPtr, nil
59+
}
60+
61+
// Create data container unit
62+
func (c *FleetClient) createDataUnit(component string) (unitName string, unitPtr *unit.Unit, err error) {
63+
unitName, err = formatUnitName(component, 0)
64+
if err != nil {
65+
return
66+
}
67+
machineID, err := randomMachineID(c)
68+
if err != nil {
69+
return
70+
}
71+
unitPtr, err = NewDataUnit(component, machineID)
72+
if err != nil {
73+
return
74+
}
75+
return unitName, unitPtr, nil
76+
77+
}

client/destroy.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package client
2+
3+
import "fmt"
4+
5+
// Destroy unschedules one unit for a given component type
6+
func (c *FleetClient) Destroy(component string) (err error) {
7+
num, err := c.lastUnit(component)
8+
if err != nil {
9+
return
10+
}
11+
if num == 0 {
12+
return fmt.Errorf("no units to destroy")
13+
}
14+
unitName, err := formatUnitName(component, num)
15+
if err != nil {
16+
return
17+
}
18+
_, err = c.Fleet.Job(unitName)
19+
if err != nil {
20+
return
21+
}
22+
if err = c.Fleet.DestroyJob(unitName); err != nil {
23+
return fmt.Errorf("failed destroying job %s: %v", unitName, err)
24+
}
25+
fmt.Printf("Destroyed Unit %s\n", unitName)
26+
return
27+
}

client/fleet.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package client
2+
3+
import "github.com/coreos/fleet/client"
4+
5+
// FleetClient used to wrap Fleet API calls
6+
type FleetClient struct {
7+
Fleet client.API
8+
}
9+
10+
// NewClient returns a client used to communicate with Fleet
11+
// using the Registry API
12+
func NewClient() (*FleetClient, error) {
13+
client, err := getRegistryClient()
14+
if err != nil {
15+
return nil, err
16+
}
17+
// set global client
18+
cAPI = client
19+
return &FleetClient{Fleet: client}, nil
20+
}
21+
22+
// randomMachineID return a random machineID from the Fleet cluster
23+
func randomMachineID(c *FleetClient) (machineID string, err error) {
24+
machineState, err := c.Fleet.Machines()
25+
if err != nil {
26+
return "", err
27+
}
28+
var machineIDs []string
29+
for _, ms := range machineState {
30+
machineIDs = append(machineIDs, ms.ID)
31+
}
32+
return randomValue(machineIDs), nil
33+
}

client/list.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package client
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"sort"
7+
"strings"
8+
"text/tabwriter"
9+
10+
"github.com/coreos/fleet/job"
11+
"github.com/coreos/fleet/machine"
12+
)
13+
14+
// initialize tabwriter on stdout
15+
func init() {
16+
out = new(tabwriter.Writer)
17+
out.Init(os.Stdout, 0, 8, 1, '\t', 0)
18+
}
19+
20+
const (
21+
defaultListUnitFields = "unit,state,load,active,sub,desc,machine"
22+
)
23+
24+
type jobToField func(j *job.Job, full bool) string
25+
26+
var (
27+
out *tabwriter.Writer
28+
listUnitsFields = map[string]jobToField{
29+
"unit": func(j *job.Job, full bool) string {
30+
return j.Name
31+
},
32+
"state": func(j *job.Job, full bool) string {
33+
js := j.State
34+
if js != nil {
35+
return string(*js)
36+
}
37+
return "-"
38+
},
39+
"dstate": func(j *job.Job, full bool) string {
40+
return string(j.TargetState)
41+
},
42+
"load": func(j *job.Job, full bool) string {
43+
us := j.UnitState
44+
if us == nil {
45+
return "-"
46+
}
47+
return us.LoadState
48+
},
49+
"active": func(j *job.Job, full bool) string {
50+
us := j.UnitState
51+
if us == nil {
52+
return "-"
53+
}
54+
return us.ActiveState
55+
},
56+
"sub": func(j *job.Job, full bool) string {
57+
us := j.UnitState
58+
if us == nil {
59+
return "-"
60+
}
61+
return us.SubState
62+
},
63+
"desc": func(j *job.Job, full bool) string {
64+
d := j.Unit.Description()
65+
if d == "" {
66+
return "-"
67+
}
68+
return d
69+
},
70+
"machine": func(j *job.Job, full bool) string {
71+
us := j.UnitState
72+
if us == nil || us.MachineID == "" {
73+
return "-"
74+
}
75+
ms := cachedMachineState(us.MachineID)
76+
if ms == nil {
77+
ms = &machine.MachineState{ID: us.MachineID}
78+
}
79+
return machineFullLegend(*ms, full)
80+
},
81+
"tmachine": func(j *job.Job, full bool) string {
82+
if j.TargetMachineID == "" {
83+
return "-"
84+
}
85+
ms := cachedMachineState(j.TargetMachineID)
86+
if ms == nil {
87+
ms = &machine.MachineState{ID: j.TargetMachineID}
88+
}
89+
return machineFullLegend(*ms, full)
90+
},
91+
"hash": func(j *job.Job, full bool) string {
92+
us := j.UnitState
93+
if us == nil || us.UnitHash == "" {
94+
return "-"
95+
}
96+
if !full {
97+
return us.UnitHash[:7]
98+
}
99+
return us.UnitHash
100+
},
101+
}
102+
)
103+
104+
// List prints all Deis-related units to Stdout
105+
func (c *FleetClient) List() (err error) {
106+
107+
var jobs map[string]job.Job
108+
var sortable sort.StringSlice
109+
110+
jobs = make(map[string]job.Job, 0)
111+
jj, err := c.Fleet.Jobs()
112+
if err != nil {
113+
return err
114+
}
115+
for _, j := range jj {
116+
if strings.HasPrefix(j.Name, "deis-") {
117+
jobs[j.Name] = j
118+
sortable = append(sortable, j.Name)
119+
}
120+
}
121+
sortable.Sort()
122+
printList(jobs, sortable)
123+
return
124+
}
125+
126+
// printList writes units to stdout using a tabwriter
127+
func printList(jobs map[string]job.Job, sortable sort.StringSlice) {
128+
cols := strings.Split(defaultListUnitFields, ",")
129+
for _, s := range cols {
130+
if _, ok := listUnitsFields[s]; !ok {
131+
fmt.Fprintf(os.Stderr, "Invalid key in output format: %q\n", s)
132+
}
133+
}
134+
fmt.Fprintln(out, strings.ToUpper(strings.Join(cols, "\t")))
135+
for _, name := range sortable {
136+
var f []string
137+
j := jobs[name]
138+
for _, c := range cols {
139+
f = append(f, listUnitsFields[c](&j, false))
140+
}
141+
fmt.Fprintln(out, strings.Join(f, "\t"))
142+
}
143+
out.Flush()
144+
}
145+
146+
func machineIDLegend(ms machine.MachineState, full bool) string {
147+
legend := ms.ID
148+
if !full {
149+
legend = fmt.Sprintf("%s...", ms.ShortID())
150+
}
151+
return legend
152+
}
153+
154+
func machineFullLegend(ms machine.MachineState, full bool) string {
155+
legend := machineIDLegend(ms, full)
156+
if len(ms.PublicIP) > 0 {
157+
legend = fmt.Sprintf("%s/%s", legend, ms.PublicIP)
158+
}
159+
return legend
160+
}

client/registry.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package client
2+
3+
import (
4+
"crypto/tls"
5+
"fmt"
6+
"net"
7+
"net/http"
8+
"strings"
9+
"time"
10+
11+
"github.com/coreos/fleet/client"
12+
"github.com/coreos/fleet/machine"
13+
"github.com/coreos/fleet/registry"
14+
"github.com/coreos/fleet/ssh"
15+
)
16+
17+
// Flags used for Fleet API connectivity
18+
var Flags = struct {
19+
Debug bool
20+
Verbosity int
21+
Version bool
22+
Endpoint string
23+
EtcdKeyPrefix string
24+
UseAPI bool
25+
KnownHostsFile string
26+
StrictHostKeyChecking bool
27+
Tunnel string
28+
}{}
29+
30+
// global API client used by commands
31+
var cAPI client.API
32+
33+
// used to cache MachineStates
34+
var machineStates map[string]*machine.MachineState
35+
var requestTimeout = time.Duration(10) * time.Second
36+
37+
func getTunnelFlag() string {
38+
tun := Flags.Tunnel
39+
if tun != "" && !strings.Contains(tun, ":") {
40+
tun += ":22"
41+
}
42+
return tun
43+
}
44+
45+
func getChecker() *ssh.HostKeyChecker {
46+
if !Flags.StrictHostKeyChecking {
47+
return nil
48+
}
49+
keyFile := ssh.NewHostKeyFile(Flags.KnownHostsFile)
50+
return ssh.NewHostKeyChecker(keyFile)
51+
}
52+
53+
func getFakeClient() (*registry.FakeRegistry, error) {
54+
return registry.NewFakeRegistry(), nil
55+
}
56+
57+
func getRegistryClient() (client.API, error) {
58+
var dial func(string, string) (net.Conn, error)
59+
tun := getTunnelFlag()
60+
if tun != "" {
61+
sshClient, err := ssh.NewSSHClient("core", tun, getChecker(), false)
62+
if err != nil {
63+
return nil, fmt.Errorf("failed initializing SSH client: %v", err)
64+
}
65+
dial = func(network, addr string) (net.Conn, error) {
66+
tcpaddr, err := net.ResolveTCPAddr(network, addr)
67+
if err != nil {
68+
return nil, err
69+
}
70+
return sshClient.DialTCP(network, nil, tcpaddr)
71+
}
72+
}
73+
trans := http.Transport{
74+
Dial: dial,
75+
TLSClientConfig: &tls.Config{
76+
InsecureSkipVerify: true,
77+
},
78+
}
79+
return client.NewRegistryClient(&trans, Flags.Endpoint, Flags.EtcdKeyPrefix, requestTimeout)
80+
}

0 commit comments

Comments
 (0)