Skip to content

Commit 8b9455d

Browse files
author
Gabriel Monroy
committed
initial commit
0 parents  commit 8b9455d

26 files changed

Lines changed: 1262 additions & 0 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package/

Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM deis/base
2+
ADD https://storage.googleapis.com/golang/go1.3.linux-amd64.tar.gz /tmp/
3+
RUN tar -C /usr/local -xzf /tmp/go1.3.linux-amd64.tar.gz
4+
RUN apt-get update && apt-get install -yq git mercurial
5+
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/go/bin
6+
ENV GOPATH /go
7+
ADD . /go/src/github.com/deis/deis/deisctl
8+
ADD units /tmp/package/var/lib/deis/units
9+
WORKDIR /go/src/github.com/deis/deis/deisctl
10+
RUN cd deisctl && go get -v . && go install -v .
11+
RUN mkdir -p /tmp/package/opt/bin && cp /go/bin/deisctl /tmp/package/opt/bin/deisctl
12+
RUN tar -C /tmp/package -czf /tmp/deisctl.tar.gz .
13+
ENTRYPOINT ["/go/bin/deisctl"]

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
COMPONENTS=builder cache controller database logger registry router
2+
3+
build:
4+
go build .
5+
6+
package:
7+
rm -f package
8+
docker build -t deis/deisctl .
9+
-docker cp $(shell docker run -d deis/deisctl):/tmp/deisctl.tar.gz package/

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Deis Control Utility
2+
3+
`deisctl` is a command-line utility used to operate a Deis cluster.
4+
5+
## Build
6+
7+
```
8+
make build
9+
```
10+
11+
## Usage
12+
13+
### Install Deis
14+
15+
```
16+
deisctl install
17+
```

client.go

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
package deisctl
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"sort"
7+
"strings"
8+
9+
"github.com/coreos/fleet/client"
10+
"github.com/coreos/fleet/job"
11+
)
12+
13+
// Client interface used to interact with the cluster control plane
14+
type Client interface {
15+
Create(string) error
16+
Destroy(string) error
17+
Start(string) error
18+
Stop(string) error
19+
Scale(string, int) error
20+
List() error
21+
Status(string) error
22+
}
23+
24+
// FleetClient used to wrap Fleet API calls
25+
type FleetClient struct {
26+
Fleet client.API
27+
}
28+
29+
// NewClient returns a client used to communicate with Fleet
30+
// using the Registry API
31+
func NewClient() (*FleetClient, error) {
32+
client, err := getRegistryClient()
33+
if err != nil {
34+
return nil, err
35+
}
36+
return &FleetClient{Fleet: client}, nil
37+
}
38+
39+
// Create schedules a new unit for the given component
40+
// and blocks until the unit is loaded
41+
func (c *FleetClient) Create(component string) (err error) {
42+
num, err := c.nextUnit(component)
43+
if err != nil {
44+
return
45+
}
46+
unitName, err := formatUnitName(component, num)
47+
if err != nil {
48+
return
49+
}
50+
unit, err := NewUnit(component)
51+
if err != nil {
52+
return
53+
}
54+
j := job.NewJob(unitName, *unit)
55+
if err := c.Fleet.CreateJob(j); err != nil {
56+
return fmt.Errorf("failed creating job %s: %v", unitName, err)
57+
}
58+
newState := job.JobStateLoaded
59+
err = c.Fleet.SetJobTargetState(unitName, newState)
60+
if err != nil {
61+
return err
62+
}
63+
errchan := waitForJobStates(c.Fleet, []string{unitName}, testJobStateLoaded, 0, os.Stdout)
64+
for err := range errchan {
65+
return fmt.Errorf("error waiting for job %s: %v", unitName, err)
66+
}
67+
return nil
68+
}
69+
70+
// Destroy unschedules one unit for a given component type
71+
func (c *FleetClient) Destroy(component string) (err error) {
72+
num, err := c.lastUnit(component)
73+
if err != nil {
74+
return
75+
}
76+
if num == 0 {
77+
return fmt.Errorf("no units to destroy")
78+
}
79+
unitName, err := formatUnitName(component, num)
80+
if err != nil {
81+
return
82+
}
83+
_, err = c.Fleet.Job(unitName)
84+
if err != nil {
85+
return
86+
}
87+
if err = c.Fleet.DestroyJob(unitName); err != nil {
88+
return fmt.Errorf("failed destroying job %s: %v", unitName, err)
89+
}
90+
fmt.Printf("Destroyed Unit %s\n", unitName)
91+
return
92+
}
93+
94+
// Scale creates or destroys units to match the desired number
95+
func (c *FleetClient) Scale(component string, num int) (err error) {
96+
for {
97+
components, err := c.getUnits(component)
98+
if err != nil {
99+
return err
100+
}
101+
if len(components) == num {
102+
break
103+
}
104+
if len(components) < num {
105+
c.Create(component)
106+
continue
107+
}
108+
if len(components) > num {
109+
c.Destroy(component)
110+
continue
111+
}
112+
}
113+
return
114+
}
115+
116+
// Start launches target units and blocks until active
117+
func (c *FleetClient) Start(target string) (err error) {
118+
units, err := c.getUnits(target)
119+
if err != nil {
120+
return
121+
}
122+
newState := job.JobStateLaunched
123+
for _, unitName := range units {
124+
err = c.Fleet.SetJobTargetState(unitName, newState)
125+
if err != nil {
126+
return err
127+
}
128+
}
129+
errchan := waitForJobStates(c.Fleet, units, testUnitStateActive, 0, os.Stdout)
130+
for err := range errchan {
131+
return fmt.Errorf("error waiting for active: %v", err)
132+
}
133+
return nil
134+
}
135+
136+
// Stop sets target units to inactive and blocks until complete
137+
func (c *FleetClient) Stop(target string) (err error) {
138+
units, err := c.getUnits(target)
139+
if err != nil {
140+
return
141+
}
142+
newState := job.JobStateInactive
143+
for _, unitName := range units {
144+
err = c.Fleet.SetJobTargetState(unitName, newState)
145+
if err != nil {
146+
return err
147+
}
148+
}
149+
errchan := waitForJobStates(c.Fleet, units, testJobStateInactive, 0, os.Stdout)
150+
for err := range errchan {
151+
return fmt.Errorf("error waiting for inactive: %v", err)
152+
}
153+
return nil
154+
}
155+
156+
// List prints all Deis-related units to Stdout
157+
func (c *FleetClient) List() (err error) {
158+
159+
var jobs map[string]job.Job
160+
var sortable sort.StringSlice
161+
162+
jobs = make(map[string]job.Job, 0)
163+
jj, err := c.Fleet.Jobs()
164+
if err != nil {
165+
return err
166+
}
167+
for _, j := range jj {
168+
if strings.HasPrefix(j.Name, "deis-") {
169+
jobs[j.Name] = j
170+
sortable = append(sortable, j.Name)
171+
}
172+
}
173+
sortable.Sort()
174+
printList(jobs, sortable)
175+
return
176+
}
177+
178+
// Status prints the systemd status of target unit(s)
179+
func (c *FleetClient) Status(target string) (err error) {
180+
units, err := c.getUnits(target)
181+
if err != nil {
182+
return
183+
}
184+
for _, unit := range units {
185+
printUnitStatus(c.Fleet, unit)
186+
fmt.Println()
187+
}
188+
return
189+
}
190+
191+
// getUnits returns a list of units filtered by target
192+
func (c *FleetClient) getUnits(target string) (units []string, err error) {
193+
jobs, err := c.Fleet.Jobs()
194+
if err != nil {
195+
return
196+
}
197+
for _, j := range jobs {
198+
if strings.HasPrefix(j.Name, "deis-"+target) {
199+
units = append(units, j.Name)
200+
}
201+
}
202+
return
203+
}
204+
205+
// nextUnit returns the next unit number for a given component
206+
func (c *FleetClient) nextUnit(component string) (num int, err error) {
207+
units, err := c.getUnits(component)
208+
if err != nil {
209+
return
210+
}
211+
num, err = nextUnitNum(units)
212+
if err != nil {
213+
return
214+
}
215+
return
216+
}
217+
218+
// lastUnit returns the last unit number for a given component
219+
func (c *FleetClient) lastUnit(component string) (num int, err error) {
220+
units, err := c.getUnits(component)
221+
if err != nil {
222+
return
223+
}
224+
num, err = lastUnitNum(units)
225+
if err != nil {
226+
return
227+
}
228+
return
229+
}

0 commit comments

Comments
 (0)