Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ ENV PROJECTPATH=/go/src/github.com/replicatedhq/replicated

RUN go get golang.org/x/tools/cmd/goimports

RUN go get github.com/spf13/cobra/cobra

RUN go get github.com/go-swagger/go-swagger/cmd/swagger

WORKDIR $PROJECTPATH

CMD ["/bin/bash"]
63 changes: 38 additions & 25 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
API_PKGS=apps channels releases

docker:
docker build -t replicatedhq.replicated .

Expand All @@ -7,38 +9,49 @@ shell:
replicatedhq.replicated

clean:
rm -rf gen
sudo rm -rf gen/go

deps:
docker run --rm \
--volume `pwd`:/go/src/github.com/replicatedhq/replicated \
replicatedhq.replicated glide install

test:
go test ./client
go test ./cli/test

gen:
docker run --rm \
--volume `pwd`:/local \
swaggerapi/swagger-codegen-cli generate \
-Dmodels -DmodelsDocs=false \
-i https://api.replicated.com/vendor/v1/spec/channels.json \
-l go \
-o /local/gen/go/channels
docker run --rm \
--volume `pwd`:/local \
swaggerapi/swagger-codegen-cli generate \
-Dmodels -DmodelsDocs=false \
-i https://api.replicated.com/vendor/v1/spec/releases.json \
-l go \
-o /local/gen/go/releases
sudo chown -R ${USER}:${USER} gen/
# fix time.Time fields. Codegen generates empty Time struct.
rm gen/go/releases/time.go
sed -i 's/Time/time.Time/' gen/go/releases/app_release_info.go
# import "time"
# fetch the swagger specs from the production Vendor API
get-spec-prod:
mkdir -p gen/spec/
for PKG in ${API_PKGS}; do \
curl -o gen/spec/$$PKG.json \
https://api.replicated.com/vendor/v1/spec/$$PKG.json; \
done

# generate the swagger specs from the local replicatedcom/vendor-api repo
get-spec-local:
mkdir -p gen/spec/
docker run --rm \
--volume `pwd`:/go/src/github.com/replicatedhq/replicated \
replicatedhq.replicated goimports -w gen/go/releases
--volume ${GOPATH}/src/github.com:/go/src/github.com \
replicatedhq.replicated /bin/bash -c ' \
for PKG in ${API_PKGS}; do \
swagger generate spec \
-b ../../replicatedcom/vendor-api/handlers/replv1/$$PKG \
-o gen/spec/$$PKG.json; \
done'

gen-models:
for PKG in ${API_PKGS}; do \
docker run --rm \
--volume `pwd`:/local \
swaggerapi/swagger-codegen-cli generate \
-Dmodels -DmodelsDocs=false \
-i /local/gen/spec/$$PKG.json \
-l go \
-o /local/gen/go/$$PKG; \
done

build: deps gen-models

build: deps gen
install:
go build -o replicated cli/main.go
mv replicated ${GOPATH}/bin
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
This repository provides a client and CLI for interacting with the Replicated Vendor API.
The models are generated from the API's swagger spec.

## Tests
Set the following env vars to run integration tests against the Vendor API.
* VENDOR_API_KEY
* VENDOR_API_ORIGIN
* VENDOR_APP_ID
Set the following env vars to avoid passing them as arguments to each command.
* REPLICATED_APP_SLUG
* REPLICATED_API_TOKEN
```REPLICATED_API_ORIGIN``` may also be set for testing.
16 changes: 16 additions & 0 deletions cli/cmd/channel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cmd

import (
"github.com/spf13/cobra"
)

// channelCmd represents the channel command
var channelCmd = &cobra.Command{
Use: "channel",
Short: "Manage and review channels",
Long: "Manage and review channels",
}

func init() {
RootCmd.AddCommand(channelCmd)
}
34 changes: 34 additions & 0 deletions cli/cmd/channel_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cmd

import (
"github.com/replicatedhq/replicated/cli/print"
"github.com/spf13/cobra"
)

var channelCreateCmd = &cobra.Command{
Use: "create",
Short: "Create a new channel in your app",
Long: `Create a new channel in your app and print the full set of channels in the app on success.

Example:
replicated channel create --name Beta --description 'New features subject to change'`,
}

var channelCreateName string
var channelCreateDescription string

func init() {
channelCmd.AddCommand(channelCreateCmd)

channelCreateCmd.Flags().StringVar(&channelCreateName, "name", "", "The name of this channel")
channelCreateCmd.Flags().StringVar(&channelCreateDescription, "description", "", "A longer description of this channel")
}

func (r *runners) channelCreate(cmd *cobra.Command, args []string) error {
allChannels, err := r.api.CreateChannel(r.appID, channelCreateName, channelCreateDescription)
if err != nil {
return err
}

return print.Channels(r.w, allChannels)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be awesome if printers supported formats eg tabs, json, yaml

}
59 changes: 59 additions & 0 deletions cli/cmd/channel_inspect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"

"github.com/replicatedhq/replicated/cli/print"
)

// channelInspectCmd represents the channelInspect command
var channelInspectCmd = &cobra.Command{
Use: "inspect",
Short: "Show full details for a channel",
Long: "Show full details for a channel",
}

func init() {
channelCmd.AddCommand(channelInspectCmd)
}

func (r *runners) channelInspect(cmd *cobra.Command, args []string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im concerned about how parseable this output is. a lot of ppl will use cli for automation

if len(args) != 1 {
return fmt.Errorf(cmd.UsageString())
}
chanID := args[0]

appChan, releases, err := r.api.GetChannel(r.appID, chanID)
if err != nil {
return err
}

if err = print.ChannelAttrs(r.w, appChan); err != nil {
return err
}

if _, err = fmt.Fprint(r.w, "\nADOPTION\n"); err != nil {
return err
}
if err = print.ChannelAdoption(r.w, &appChan.Adoption); err != nil {
return err
}

if _, err = fmt.Fprint(r.w, "\nLICENSE_COUNTS\n"); err != nil {
return err
}
if err = print.LicenseCounts(r.w, &appChan.LicenseCounts); err != nil {
return err
}

if _, err = fmt.Fprint(r.w, "\nRELEASES\n"); err != nil {
return err
}
if err = print.ChannelReleases(r.w, releases); err != nil {
return err
}

return nil
}
26 changes: 26 additions & 0 deletions cli/cmd/channel_ls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cmd

import (
"github.com/replicatedhq/replicated/cli/print"
"github.com/spf13/cobra"
)

// channelLsCmd represents the channelLs command
var channelLsCmd = &cobra.Command{
Use: "ls",
Short: "List all channels in your app",
Long: "List all channels in your app",
}

func init() {
channelCmd.AddCommand(channelLsCmd)
}

func (r *runners) channelList(cmd *cobra.Command, args []string) error {
channels, err := r.api.ListChannels(r.appID)
if err != nil {
return err
}

return print.Channels(r.w, channels)
}
35 changes: 35 additions & 0 deletions cli/cmd/channel_rm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

// channelRmCmd represents the channelRm command
var channelRmCmd = &cobra.Command{
Use: "rm CHANNEL_ID",
Short: "Remove (archive) a channel",
Long: "Remove (archive) a channel",
}

func init() {
channelCmd.AddCommand(channelRmCmd)
}

func (r *runners) channelRemove(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
return fmt.Errorf("channel ID is required")
}
chanID := args[0]

if err := r.api.ArchiveChannel(r.appID, chanID); err != nil {
return err
}

// ignore the error since operation was successful
fmt.Fprintf(r.w, "Channel %s successfully archived\n", chanID)
r.w.Flush()

return nil
}
20 changes: 20 additions & 0 deletions cli/cmd/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package cmd

import (
"crypto/rand"
"encoding/base64"
"io"
"testing"
)

// generate a random string or call t.Fatal
func token(t *testing.T, n int) string {
if n == 0 {
n = 256
}
data := make([]byte, int(n))
if _, err := io.ReadFull(rand.Reader, data); err != nil {
t.Fatal(err)
}
return base64.RawURLEncoding.EncodeToString(data)
}
16 changes: 16 additions & 0 deletions cli/cmd/release.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cmd

import (
"github.com/spf13/cobra"
)

// releaseCmd represents the release command
var releaseCmd = &cobra.Command{
Use: "release",
Short: "Manage app releases",
Long: `The release command allows vendors to create, display, modify, and archive their releases.`,
}

func init() {
RootCmd.AddCommand(releaseCmd)
}
45 changes: 45 additions & 0 deletions cli/cmd/release_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

var createReleaseYaml string

var releaseCreateCmd = &cobra.Command{
Use: "create",
Short: "Create a new release",
Long: `Create a new release by providing YAML configuration for the next release in
your sequence.`,
}

func init() {
releaseCmd.AddCommand(releaseCreateCmd)

releaseCreateCmd.Flags().StringVar(&createReleaseYaml, "yaml", "", "The YAML config for this release")
}

func (r *runners) releaseCreate(cmd *cobra.Command, args []string) error {
if createReleaseYaml == "" {
return fmt.Errorf("yaml is required")
}

// API does not accept yaml in create operation, so first create then udpate
release, err := r.api.CreateRelease(r.appID)
if err != nil {
return err
}

if _, err := fmt.Fprintf(r.w, "SEQUENCE: %d\n", release.Sequence); err != nil {
return err
}
r.w.Flush()

if err := r.api.UpdateRelease(r.appID, release.Sequence, createReleaseYaml); err != nil {
return fmt.Errorf("Failure setting yaml config for release: %v", err)
}

return nil
}
Loading