@nkhumphreys
29th June 2015
nkhumphreys.co.uk
GDG Berlin GoLang
nkhumphreys.co.uk
Who am I
nkhumphreys.co.uk
What is ZenMate
nkhumphreys.co.uk
What I will say
nkhumphreys.co.uk
The World that was
kill unicorns
kill rabbits
kill god
nkhumphreys.co.uk
The World that was...
nkhumphreys.co.uk
The World that was...
Managing infrastructure looked like this
nkhumphreys.co.uk
The World that was...
When DevOps wanted it to look like this
nkhumphreys.co.uk
Why swap
We decided to build it, to make our DevOps lead look like this:
GOAL =>
nkhumphreys.co.uk
Why swap at all?
nkhumphreys.co.uk
First steps
Decisions
nkhumphreys.co.uk
Obvious choice
nkhumphreys.co.uk
Obvious choice
nkhumphreys.co.uk
Best day of my Career
One of my most productive days was throwing away 1,000 lines of code.
Ken Thompson
nkhumphreys.co.uk
Best day of my Career
Replacing 2,234 lines of Ruby with ~600 lines of GoLang
nkhumphreys.co.uk
Deployment
supervisorctl restart <insert_service_name>
nkhumphreys.co.uk
Services for more than infrastructure
nkhumphreys.co.uk
Keeping everyone happy
Marketing also had to use this
nkhumphreys.co.uk
Keeping everyone happy
nkhumphreys.co.uk
Keeping everyone happy
Which made them look like this
nkhumphreys.co.uk
Easy-to-use is subjective
nkhumphreys.co.uk
Tailor made UI
Gopher to the rescue, again!
nkhumphreys.co.uk
Tailor made UI
A little Bootstrap and JQuery, et voila
nkhumphreys.co.uk
Features that helped
Anonymous structures
// handleGetAdminHomePage renders the single page javascript application for
// the admin interface
func handleGetAdminHomePage(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
log.Println("serving Admin")
context := struct {
News []CompleteNewsItem
AllPlatforms []string
}{
getCompleteNewsItems(),
getSupportedPlatforms(),
}
templates.ExecuteTemplate(w, "list", context)
}
nkhumphreys.co.uk
Features that helped
Template language
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
{{ range $n := .News }}
<div id="news-item-{{ $n.NewsItem.ID }}" class="row">
<div class="row">
<div class="row">
<div class="col-md-6">
<h3>{{ $n.NewsItem.InternalReference }}</h3>
</div>
<div class="col-md-2">
<button data-news-id="{{ $n.NewsItem.ID }}">
Edit
</button>
</div>
nkhumphreys.co.uk
Features that helped
Struct tags for JSON rendering and database column mapping
type NewsItem struct {
ID int `json:"-" db:"id"`
InternalReference string `json:"-" db:"internal_reference"`
Content string `json:"content"`
Locale string `json:"-"`
Premium bool `json:"-" db:"premium"`
PublishAt time.Time `json:"-" db:"publish_at"`
}
nkhumphreys.co.uk
We haven't left the stdlib
nkhumphreys.co.uk
We now have two happy users
nkhumphreys.co.uk
Whats next...
SendMail(email_addr, auth, from, to, msg)
nkhumphreys.co.uk
Lessons Learned
nkhumphreys.co.uk
End Goal
nkhumphreys.co.uk
@nkhumphreys
Questions?
nkhumphreys.co.uk
@nkhumphreys
Want some ZenMate goodies?