Skip to content

Commit

Permalink
Implemented Heroku apps, dynos & builds
Browse files Browse the repository at this point in the history
  • Loading branch information
mrusme committed Mar 20, 2022
1 parent bc368ca commit 00d2674
Show file tree
Hide file tree
Showing 14 changed files with 268 additions and 5 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ following cloud service providers and cloud services:
- CloudWatch Logs
- Vultr
- Cloud Instances
- Heroku
- Dynos
- Builds
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
```
Expand Down Expand Up @@ -95,6 +98,15 @@ $ export VULTR_API_KEY='...'
$ planor -c vultr -p VULTR_API_KEY
=== Heroku ===
Run planor and specify the environment variable that holds the Heroku API key as
profile:
$ export HEROKU_API_KEY='...'
$ planor -c heroku -p HEROKU_API_KEY
CONFIGURATION
-------------
Expand Down
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,22 @@ require (
github.com/aws/aws-sdk-go-v2/service/sso v1.11.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.16.0 // indirect
github.com/aws/smithy-go v1.11.1 // indirect
github.com/cenkalti/backoff v2.1.1+incompatible // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/golang/protobuf v1.4.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.0.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
github.com/heroku/heroku-go/v5 v5.4.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect
github.com/pborman/uuid v1.2.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/sahilm/fuzzy v0.1.0 // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
Expand Down
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.16.0 h1:0+X/rJ2+DTBKWbUsn7WtF0JvNk/f
github.com/aws/aws-sdk-go-v2/service/sts v1.16.0/go.mod h1:+8k4H2ASUZZXmjx/s3DFLo9tGBb44lkz3XcgfypJY7s=
github.com/aws/smithy-go v1.11.1 h1:IQ+lPZVkSM3FRtyaDox41R8YS6iwPMYIreejOgPW49g=
github.com/aws/smithy-go v1.11.1/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY=
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/charmbracelet/bubbles v0.10.3 h1:fKarbRaObLn/DCsZO4Y3vKCwRUzynQD9L+gGev1E/ho=
github.com/charmbracelet/bubbles v0.10.3/go.mod h1:jOA+DUF1rjZm7gZHcNyIVW+YrBPALKfpGVdJu8UiJsA=
Expand Down Expand Up @@ -130,6 +132,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
Expand All @@ -142,6 +145,8 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
Expand All @@ -151,6 +156,8 @@ github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiw
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/heroku/heroku-go/v5 v5.4.1 h1:J1nNnR3/571b2iUDHl+y1B3VkhKm6YOXIq9GGzQUv5s=
github.com/heroku/heroku-go/v5 v5.4.1/go.mod h1:Uo3XhGPwaTpniR4X1e50BDjg4SzdFk2Bd2mgYZVkfHo=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
Expand Down Expand Up @@ -180,6 +187,8 @@ github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtl
github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 h1:QANkGiGr39l1EESqrE0gZw0/AJNYzIvoGLhIoVYtluI=
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
Expand Down
37 changes: 37 additions & 0 deletions nori/heroku/apps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package heroku

import (
"context"
// "errors"

"github.com/mrusme/planor/nori/models"

herokugo "github.com/heroku/heroku-go/v5"
)

func (cloud *Heroku) ListApps() ([]models.App, error) {
input := herokugo.ListRange{
Field: "id",
Max: 100,
Descending: false,
}

ret, err := cloud.heroku.AppList(context.Background(), &input)
if err != nil {
return nil, err
}

var apps []models.App
for _, app := range ret {
newApp := models.App{
ID: app.ID,
Name: app.Name,
}

apps = append(apps, newApp)
}

return apps, nil
}


50 changes: 50 additions & 0 deletions nori/heroku/ci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package heroku

import (
"context"
// "errors"

"github.com/mrusme/planor/nori/models"

herokugo "github.com/heroku/heroku-go/v5"
)

func (cloud *Heroku) ListPipelines() ([]models.Pipeline, error) {
apps, err := cloud.ListApps()
if err != nil {
return nil, err
}

var pipelines []models.Pipeline
input := herokugo.ListRange{
Field: "id",
Max: 1,
Descending: true,
}
for _, app := range apps {
ret, err := cloud.heroku.BuildList(context.Background(), app.ID, &input)
if err != nil {
return pipelines, err
}

for _, build := range ret {
newPipelineStage := models.PipelineStage {
ID: build.ID,
Name: build.Release.ID,
Status: build.Status,
}

var stages []models.PipelineStage
stages = append(stages, newPipelineStage)
newPipeline := models.Pipeline{
ID: app.ID,
Name: app.Name,
Stages: stages,
}

pipelines = append(pipelines, newPipeline)
}
}

return pipelines, nil
}
45 changes: 45 additions & 0 deletions nori/heroku/heroku.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package heroku

import (
"os"

"github.com/mrusme/planor/nori/adapter"

herokugo "github.com/heroku/heroku-go/v5"
)

type Heroku struct {
apiKey string
heroku *herokugo.Service
}

func (cloud *Heroku) LoadProfile(profile *string) (error) {
cloud.apiKey = os.Getenv(*profile)

return nil
}

func (cloud *Heroku) LoadClients() (error) {
herokugo.DefaultTransport.BearerToken = cloud.apiKey

cloud.heroku = herokugo.NewService(herokugo.DefaultClient)

return nil
}

func (cloud *Heroku) GetCapabilities() ([]adapter.Capability) {
var caps []adapter.Capability

caps = append(caps, adapter.Capability{
ID: "instances",
Name: "Dynos",
})
caps = append(caps, adapter.Capability{
ID: "ci",
Name: "Builds",
})

return caps
}


47 changes: 47 additions & 0 deletions nori/heroku/instances.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package heroku

import (
"context"
// "errors"

"github.com/mrusme/planor/nori/models"

herokugo "github.com/heroku/heroku-go/v5"
)

func (cloud *Heroku) ListInstances() ([]models.Instance, error) {
apps, err := cloud.ListApps()
if err != nil {
return nil, err
}

var dynos []models.Instance
input := herokugo.ListRange{
Field: "id",
Max: 100,
Descending: false,
}
for _, app := range apps {
ret, err := cloud.heroku.DynoList(context.Background(), app.ID, &input)
if err != nil {
return dynos, err
}

for _, dyno := range ret {
newDyno := models.Instance{
ID: dyno.ID,
Name: dyno.Name,

Type: dyno.Size,
Image: dyno.Command,

Status: dyno.State,
}

dynos = append(dynos, newDyno)
}
}

return dynos, nil
}

21 changes: 21 additions & 0 deletions nori/heroku/logs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package heroku

import (
"errors"

"github.com/mrusme/planor/nori/models"
)


func (cloud *Heroku) ListLogGroups(updateStreams bool, updateEvents bool) ([]models.LogGroup, error) {
return nil, errors.New("Unsupported")
}

func (cloud *Heroku) UpdateLogStreams(logGroup *models.LogGroup, updateEvents bool) (error) {
return errors.New("Unsupported")
}

func (cloud *Heroku) UpdateLogEvents(logStream *models.LogStream) (error) {
return errors.New("Unsupported")
}

23 changes: 23 additions & 0 deletions nori/models/apps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package models

import (
// "fmt"
)

type App struct {
ID string
Name string
}

func (app App) FilterValue() (string) {
return app.Name
}

func (app App) Title() (string) {
return app.Name
}

func (app App) Description() (string) {
return app.ID
}

2 changes: 2 additions & 0 deletions nori/models/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type Instance struct {
Image string
IPv4 string
IPv6 string

Status string
}

func (instance Instance) FilterValue() (string) {
Expand Down
3 changes: 3 additions & 0 deletions nori/nor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/mrusme/planor/nori/amazon"
"github.com/mrusme/planor/nori/vultr"
"github.com/mrusme/planor/nori/heroku"
)

type Nor interface {
Expand All @@ -32,6 +33,8 @@ func New(cloudType *string, profile *string) (Nor, error) {
cloud = new(amazon.Amazon)
case "vultr":
cloud = new(vultr.Vultr)
case "heroku":
cloud = new(heroku.Heroku)
}

err := cloud.LoadProfile(profile)
Expand Down
6 changes: 3 additions & 3 deletions planor.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import (

func main() {
var cloudProvider = "aws"
var cloudProfile = "dev.verifyplus"
var cloudProfile = ""

flag.StringVar(&cloudProvider, "c", "aws", "cloud provider: aws, vultr")
flag.StringVar(&cloudProfile, "p", "", "aws profile name, vultr api key env variable name")
flag.StringVar(&cloudProvider, "c", "aws", "cloud provider: aws, vultr, heroku")
flag.StringVar(&cloudProfile, "p", "", "aws profile name, vultr/heroku api key env variable name")
flag.Parse()

if cloudProvider == "" || cloudProfile == "" {
Expand Down
3 changes: 2 additions & 1 deletion ui/views/instances/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,9 @@ func (m *Model) renderViewport(instance *models.Instance) (string) {
var vp string = ""

vp = fmt.Sprintf(
"%s\n",
"%s\nStatus: %s\n",
instance.Name,
instance.Status,
)

vp = fmt.Sprintf(
Expand Down
Loading

0 comments on commit 00d2674

Please sign in to comment.