~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/terms-client/cmd/push_term.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2016 Canonical Ltd.
 
2
// Licensed under the GPLv3, see LICENCE file for details.
 
3
 
 
4
package cmd
 
5
 
 
6
import (
 
7
        "io/ioutil"
 
8
        "os"
 
9
        "path"
 
10
        "strings"
 
11
 
 
12
        "github.com/juju/cmd"
 
13
        "github.com/juju/errors"
 
14
        "github.com/juju/persistent-cookiejar"
 
15
        "github.com/juju/utils"
 
16
        "gopkg.in/juju/charm.v6-unstable"
 
17
        "gopkg.in/macaroon-bakery.v1/httpbakery"
 
18
        "launchpad.net/gnuflag"
 
19
 
 
20
        "github.com/juju/terms-client/api"
 
21
)
 
22
 
 
23
var (
 
24
        defaultTermServiceLocation = "http://localhost:8081"
 
25
        readFile                   = ioutil.ReadFile
 
26
        clientNew                  = func(options ...api.ClientOption) (api.Client, error) {
 
27
                return api.NewClient(options...)
 
28
        }
 
29
)
 
30
 
 
31
const pushTermDoc = `
 
32
push-term is used to create a new Terms and Conditions document.
 
33
Examples
 
34
push-term text.txt user/enterprise-plan
 
35
   creates a new Terms and Conditions with the content from 
 
36
   file text.txt and the name enterprise-plan and 
 
37
   returns the revision of the created document.
 
38
`
 
39
 
 
40
// NewPushTermCommand returns a new command that can be
 
41
// used to create new (revisions) of Terms and
 
42
// Conditions documents.
 
43
func NewPushTermCommand() *pushTermCommand {
 
44
        return &pushTermCommand{}
 
45
}
 
46
 
 
47
// pushTermCommand creates a new Terms and Conditions document.
 
48
type pushTermCommand struct {
 
49
        cmd.CommandBase
 
50
        out cmd.Output
 
51
 
 
52
        TermID               string
 
53
        TermFilename         string
 
54
        TermsServiceLocation string
 
55
}
 
56
 
 
57
// SetFlags implements Command.SetFlags.
 
58
func (c *pushTermCommand) SetFlags(f *gnuflag.FlagSet) {
 
59
        // TODO (mattyw) Replace with JUJU_TERMS
 
60
        f.StringVar(&c.TermsServiceLocation, "url", defaultTermServiceLocation, "url of the terms service")
 
61
        c.out.AddFlags(f, "yaml", cmd.DefaultFormatters)
 
62
}
 
63
 
 
64
// Info implements Command.Info.
 
65
func (c *pushTermCommand) Info() *cmd.Info {
 
66
        return &cmd.Info{
 
67
                Name:    "push-term",
 
68
                Args:    "<filename> <term id>",
 
69
                Purpose: "create new Terms and Conditions document (revision)",
 
70
                Doc:     pushTermDoc,
 
71
        }
 
72
}
 
73
 
 
74
// Init read and verifies the arguments.
 
75
func (c *pushTermCommand) Init(args []string) error {
 
76
        if len(args) < 2 {
 
77
                return errors.New("missing arguments")
 
78
        }
 
79
 
 
80
        fn, id, args := args[0], args[1], args[2:]
 
81
 
 
82
        if err := cmd.CheckEmpty(args); err != nil {
 
83
                return errors.Errorf("unknown arguments: %v", strings.Join(args, ","))
 
84
        }
 
85
 
 
86
        c.TermID = id
 
87
        c.TermFilename = fn
 
88
        return nil
 
89
}
 
90
 
 
91
// Run implements Command.Run.
 
92
func (c *pushTermCommand) Run(ctx *cmd.Context) error {
 
93
        termid, err := charm.ParseTerm(c.TermID)
 
94
        if err != nil {
 
95
                return errors.Annotatef(err, "invalid term id argument")
 
96
        }
 
97
        if termid.Revision > 0 {
 
98
                return errors.Errorf("can't specify a revision with a new term")
 
99
        }
 
100
        if termid.Tenant != "" {
 
101
                return errors.Errorf("can't specify a tenant with a new term")
 
102
        }
 
103
        data, err := readFile(c.TermFilename)
 
104
        if err != nil {
 
105
                return errors.Annotatef(err, "could not read contents of %q", c.TermFilename)
 
106
        }
 
107
 
 
108
        jar, err := cookiejar.New(&cookiejar.Options{
 
109
                Filename: cookieFile(),
 
110
        })
 
111
        if err != nil {
 
112
                return errors.Trace(err)
 
113
        }
 
114
        defer jar.Save()
 
115
        bakeryClient := httpbakery.NewClient()
 
116
        bakeryClient.Jar = jar
 
117
        bakeryClient.VisitWebPage = httpbakery.OpenWebBrowser
 
118
 
 
119
        termsClient, err := clientNew(
 
120
                api.ServiceURL(c.TermsServiceLocation),
 
121
                api.HTTPClient(bakeryClient),
 
122
        )
 
123
        if err != nil {
 
124
                return errors.Trace(err)
 
125
        }
 
126
 
 
127
        response, err := termsClient.SaveTerm(
 
128
                termid.Owner,
 
129
                termid.Name,
 
130
                string(data),
 
131
        )
 
132
        if err != nil {
 
133
                return errors.Trace(err)
 
134
        }
 
135
 
 
136
        err = c.out.Write(ctx, response)
 
137
        if err != nil {
 
138
                return errors.Trace(err)
 
139
        }
 
140
        return nil
 
141
}
 
142
 
 
143
// cookieFile returns the path to the cookie used to store authorization
 
144
// macaroons. The returned value can be overridden by setting the
 
145
// JUJU_COOKIEFILE environment variable.
 
146
func cookieFile() string {
 
147
        if file := os.Getenv("JUJU_COOKIEFILE"); file != "" {
 
148
                return file
 
149
        }
 
150
        return path.Join(utils.Home(), ".go-cookies")
 
151
}