Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(2)

Side by Side Diff: state/api/client.go

Issue 58510045: debug-log: added new debug log api and command
Patch Set: debug-log: added new debug log api and command Created 11 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 Canonical Ltd. 1 // Copyright 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 package api 4 package api
5 5
6 import ( 6 import (
7 "encoding/base64"
7 "encoding/json" 8 "encoding/json"
8 "fmt" 9 "fmt"
9 "io/ioutil" 10 "io/ioutil"
10 "net/http" 11 "net/http"
12 "net/url"
11 "os" 13 "os"
12 "time" 14 "time"
13 15
16 "code.google.com/p/go.net/websocket"
17
14 "launchpad.net/juju-core/charm" 18 "launchpad.net/juju-core/charm"
15 "launchpad.net/juju-core/constraints" 19 "launchpad.net/juju-core/constraints"
16 "launchpad.net/juju-core/instance" 20 "launchpad.net/juju-core/instance"
17 "launchpad.net/juju-core/state/api/params" 21 "launchpad.net/juju-core/state/api/params"
18 "launchpad.net/juju-core/utils" 22 "launchpad.net/juju-core/utils"
19 "launchpad.net/juju-core/version" 23 "launchpad.net/juju-core/version"
20 ) 24 )
21 25
22 // Client represents the client-accessible part of the state. 26 // Client represents the client-accessible part of the state.
23 type Client struct { 27 type Client struct {
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 var err error 456 var err error
453 if archive, err = os.Open(ch.Path); err != nil { 457 if archive, err = os.Open(ch.Path); err != nil {
454 return nil, fmt.Errorf("cannot read charm archive: %v", err) 458 return nil, fmt.Errorf("cannot read charm archive: %v", err)
455 } 459 }
456 defer archive.Close() 460 defer archive.Close()
457 default: 461 default:
458 return nil, fmt.Errorf("unknown charm type %T", ch) 462 return nil, fmt.Errorf("unknown charm type %T", ch)
459 } 463 }
460 464
461 // Prepare the upload request. 465 // Prepare the upload request.
462 » url := fmt.Sprintf("%s/charms?series=%s", c.st.serverRoot, curl.Series) 466 » url := fmt.Sprintf("https://%s/charms?series=%s", c.st.serverHostPort, c url.Series)
463 req, err := http.NewRequest("POST", url, archive) 467 req, err := http.NewRequest("POST", url, archive)
464 if err != nil { 468 if err != nil {
465 return nil, fmt.Errorf("cannot create upload request: %v", err) 469 return nil, fmt.Errorf("cannot create upload request: %v", err)
466 } 470 }
467 req.SetBasicAuth(c.st.tag, c.st.password) 471 req.SetBasicAuth(c.st.tag, c.st.password)
468 req.Header.Set("Content-Type", "application/zip") 472 req.Header.Set("Content-Type", "application/zip")
469 473
470 // Send the request. 474 // Send the request.
471 475
472 // BUG(dimitern) 2013-12-17 bug #1261780 476 // BUG(dimitern) 2013-12-17 bug #1261780
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 } 511 }
508 512
509 // AddCharm adds the given charm URL (which must include revision) to 513 // AddCharm adds the given charm URL (which must include revision) to
510 // the environment, if it does not exist yet. Local charms are not 514 // the environment, if it does not exist yet. Local charms are not
511 // supported, only charm store URLs. See also AddLocalCharm() in the 515 // supported, only charm store URLs. See also AddLocalCharm() in the
512 // client-side API. 516 // client-side API.
513 func (c *Client) AddCharm(curl *charm.URL) error { 517 func (c *Client) AddCharm(curl *charm.URL) error {
514 args := params.CharmURL{URL: curl.String()} 518 args := params.CharmURL{URL: curl.String()}
515 return c.st.Call("Client", "", "AddCharm", args, nil) 519 return c.st.Call("Client", "", "AddCharm", args, nil)
516 } 520 }
521
522 // WatchDebugLog returns a ClientDebugLog reading the debug log message.
523 // The filter allows to grep wanted lines out of the output, e.g.
524 // machines or units. The watching is started the given number of
525 // matching lines back in history.
526 func (c *Client) WatchDebugLog(lines int, filter string) (*ClientDebugLog, error ) {
527 cfg := c.st.websocketConfig
528 // Prepare URL.
529 attrs := url.Values{
530 "lines": {fmt.Sprintf("%d", lines)},
531 "filter": {filter},
532 }
533 cfg.Location = &url.URL{
534 Scheme: "wss",
535 Host: c.st.serverHostPort,
536 Path: "/log",
537 RawQuery: attrs.Encode(),
538 }
539 cfg.Header = make(http.Header)
540 setBasicAuth(cfg.Header, c.st.tag, c.st.password)
541
542 wsConn, err := websocket.DialConfig(&cfg)
543 if err != nil {
544 return nil, err
545 }
546 return &ClientDebugLog{wsConn}, nil
547 }
548
549 // ClientDebugLog represents a stream of debug log messages.
550 type ClientDebugLog struct {
551 wsConn *websocket.Conn
552 }
553
554 // Close closes the log.
555 func (c *ClientDebugLog) Close() error {
556 return c.wsConn.Close()
557 }
558
559 // SetFilter sets the filter regular expression. This
560 // setting will not take place immediately - messages
561 // already in the pipeline will still be received.
562 func (c *ClientDebugLog) SetFilter(filter string) error {
563 req := params.DebugLogRequest{Filter: filter}
564 if err := websocket.JSON.Send(c.wsConn, &req); err != nil {
565 return err
566 }
567 return nil
568 }
569
570 // Read implements io.Reader.Read.
571 func (c *ClientDebugLog) Read(buf []byte) (int, error) {
572 return c.wsConn.Read(buf)
573 }
574
575 // setBasicAuth creates an Authorization header for HTTP Basic
576 // Authentication, using the given username and password.
577 func setBasicAuth(h http.Header, username, password string) {
578 h.Set("Authorization", "Basic "+basicAuth(username, password))
579 }
580
581 // basicAuth is copied from net/http.
582 // See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt
583 // "To receive authorization, the client sends the userid and password,
584 // separated by a single colon (":") character, within a base64
585 // encoded string in the credentials."
586 // It is not meant to be urlencoded.
587 func basicAuth(username, password string) string {
588 auth := username + ":" + password
589 return base64.StdEncoding.EncodeToString([]byte(auth))
590 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b