2017-05-18 23:51:52 +02:00
|
|
|
// Licensed to Pulumi Corporation ("Pulumi") under one or more
|
|
|
|
// contributor license agreements. See the NOTICE file distributed with
|
|
|
|
// this work for additional information regarding copyright ownership.
|
|
|
|
// Pulumi licenses this file to You under the Apache License, Version 2.0
|
|
|
|
// (the "License"); you may not use this file except in compliance with
|
|
|
|
// the License. You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2016-11-15 20:30:34 +01:00
|
|
|
|
|
|
|
package diag
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
2016-11-17 02:52:14 +01:00
|
|
|
"io"
|
2016-11-15 20:30:34 +01:00
|
|
|
"os"
|
2016-11-16 03:00:43 +01:00
|
|
|
"path/filepath"
|
2016-11-15 20:30:34 +01:00
|
|
|
"strconv"
|
2016-11-16 01:30:10 +01:00
|
|
|
|
|
|
|
"github.com/golang/glog"
|
2017-02-10 02:26:49 +01:00
|
|
|
|
2017-05-18 20:38:28 +02:00
|
|
|
"github.com/pulumi/lumi/pkg/diag/colors"
|
|
|
|
"github.com/pulumi/lumi/pkg/util/contract"
|
2016-11-15 20:30:34 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// Sink facilitates pluggable diagnostics messages.
|
|
|
|
type Sink interface {
|
|
|
|
// Count fetches the total number of diagnostics issued (errors plus warnings).
|
|
|
|
Count() int
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
// Infos fetches the number of debug messages issued.
|
|
|
|
Debugs() int
|
2017-02-23 03:53:36 +01:00
|
|
|
// Infos fetches the number of informational messages issued.
|
|
|
|
Infos() int
|
2016-11-15 20:30:34 +01:00
|
|
|
// Errors fetches the number of errors issued.
|
|
|
|
Errors() int
|
|
|
|
// Warnings fetches the number of warnings issued.
|
|
|
|
Warnings() int
|
2016-11-22 18:40:09 +01:00
|
|
|
// Success returns true if this sink is currently error-free.
|
|
|
|
Success() bool
|
2016-11-15 20:30:34 +01:00
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
// Logf issues a log message.
|
|
|
|
Logf(sev Severity, diag *Diag, args ...interface{})
|
|
|
|
// Debugf issues a debugging message.
|
|
|
|
Debugf(diag *Diag, args ...interface{})
|
2017-02-23 03:53:36 +01:00
|
|
|
// Infof issues an informational message.
|
|
|
|
Infof(diag *Diag, args ...interface{})
|
|
|
|
// Errorf issues a new error diagnostic.
|
2016-11-15 20:30:34 +01:00
|
|
|
Errorf(diag *Diag, args ...interface{})
|
2017-02-23 03:53:36 +01:00
|
|
|
// Warningf issues a new warning diagnostic.
|
2016-11-15 20:30:34 +01:00
|
|
|
Warningf(diag *Diag, args ...interface{})
|
2016-11-16 04:16:02 +01:00
|
|
|
|
2017-05-18 20:38:28 +02:00
|
|
|
// Stringify stringifies a diagnostic in the usual way (e.g., "error: MU123: Lumi.yaml:7:39: error goes here\n").
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
Stringify(sev Severity, diag *Diag, args ...interface{}) string
|
2017-02-12 18:38:19 +01:00
|
|
|
// StringifyLocation stringifies a source document location.
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
StringifyLocation(sev Severity, doc *Document, loc *Location) string
|
2017-02-10 02:26:49 +01:00
|
|
|
}
|
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
// Severity dictates the kind of diagnostic.
|
|
|
|
type Severity string
|
2017-02-10 02:26:49 +01:00
|
|
|
|
|
|
|
const (
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
Debug Severity = "debug"
|
|
|
|
Info Severity = "info"
|
|
|
|
Warning Severity = "warning"
|
|
|
|
Error Severity = "error"
|
2017-02-10 02:26:49 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// FormatOptions controls the output style and content.
|
|
|
|
type FormatOptions struct {
|
|
|
|
Pwd string // the working directory.
|
|
|
|
Colors bool // if true, output will be colorized.
|
2016-11-15 20:30:34 +01:00
|
|
|
}
|
|
|
|
|
2017-01-28 00:42:39 +01:00
|
|
|
// DefaultSink returns a default sink that simply logs output to stderr/stdout.
|
2017-02-10 02:26:49 +01:00
|
|
|
func DefaultSink(opts FormatOptions) Sink {
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
return newDefaultSink(opts, map[Severity]io.Writer{
|
2017-02-23 03:53:36 +01:00
|
|
|
Info: os.Stdout,
|
|
|
|
Error: os.Stderr,
|
|
|
|
Warning: os.Stdout,
|
|
|
|
})
|
2016-11-17 02:52:14 +01:00
|
|
|
}
|
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
func newDefaultSink(opts FormatOptions, writers map[Severity]io.Writer) *defaultSink {
|
2017-02-23 03:53:36 +01:00
|
|
|
contract.Assert(writers[Info] != nil)
|
|
|
|
contract.Assert(writers[Error] != nil)
|
|
|
|
contract.Assert(writers[Warning] != nil)
|
|
|
|
return &defaultSink{
|
|
|
|
opts: opts,
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
counts: make(map[Severity]int),
|
2017-02-23 03:53:36 +01:00
|
|
|
writers: writers,
|
|
|
|
}
|
2016-11-15 20:30:34 +01:00
|
|
|
}
|
|
|
|
|
2017-05-18 20:38:28 +02:00
|
|
|
const DefaultSinkIDPrefix = "LUMI"
|
2016-11-16 17:19:26 +01:00
|
|
|
|
2016-11-16 01:30:10 +01:00
|
|
|
// defaultSink is the default sink which logs output to stderr/stdout.
|
|
|
|
type defaultSink struct {
|
2017-02-23 03:53:36 +01:00
|
|
|
opts FormatOptions // a set of options that control output style and content.
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
counts map[Severity]int // the number of messages that have been issued per severity.
|
|
|
|
writers map[Severity]io.Writer // the writers to use for each kind of diagnostic severity.
|
2016-11-15 20:30:34 +01:00
|
|
|
}
|
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
func (d *defaultSink) Count() int { return d.Debugs() + d.Infos() + d.Errors() + d.Warnings() }
|
|
|
|
func (d *defaultSink) Debugs() int { return d.counts[Debug] }
|
2017-02-23 03:53:36 +01:00
|
|
|
func (d *defaultSink) Infos() int { return d.counts[Info] }
|
|
|
|
func (d *defaultSink) Errors() int { return d.counts[Error] }
|
|
|
|
func (d *defaultSink) Warnings() int { return d.counts[Warning] }
|
|
|
|
func (d *defaultSink) Success() bool { return d.Errors() == 0 }
|
2016-11-15 20:30:34 +01:00
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
func (d *defaultSink) Logf(sev Severity, diag *Diag, args ...interface{}) {
|
|
|
|
switch sev {
|
|
|
|
case Debug:
|
|
|
|
d.Debugf(diag, args...)
|
|
|
|
case Info:
|
|
|
|
d.Infof(diag, args...)
|
|
|
|
case Warning:
|
|
|
|
d.Warningf(diag, args...)
|
|
|
|
case Error:
|
|
|
|
d.Errorf(diag, args...)
|
|
|
|
default:
|
|
|
|
contract.Failf("Unrecognized severity: %v", sev)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *defaultSink) Debugf(diag *Diag, args ...interface{}) {
|
|
|
|
msg := d.Stringify(Debug, diag, args...)
|
|
|
|
if glog.V(5) {
|
|
|
|
glog.V(5).Infof("defaultSink::Debug(%v)", msg[:len(msg)-1])
|
|
|
|
}
|
|
|
|
// For debug messages, we print to glog rather than a standard io.Writer.
|
|
|
|
glog.V(3).Infoln(msg)
|
|
|
|
d.counts[Debug]++
|
|
|
|
}
|
|
|
|
|
2017-02-23 03:53:36 +01:00
|
|
|
func (d *defaultSink) Infof(diag *Diag, args ...interface{}) {
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
msg := d.Stringify(Info, diag, args...)
|
|
|
|
if glog.V(5) {
|
|
|
|
glog.V(5).Infof("defaultSink::Info(%v)", msg[:len(msg)-1])
|
2017-02-23 03:53:36 +01:00
|
|
|
}
|
|
|
|
fmt.Fprintf(d.writers[Info], msg)
|
|
|
|
d.counts[Info]++
|
2016-11-22 18:40:09 +01:00
|
|
|
}
|
|
|
|
|
2016-11-16 01:30:10 +01:00
|
|
|
func (d *defaultSink) Errorf(diag *Diag, args ...interface{}) {
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
msg := d.Stringify(Error, diag, args...)
|
|
|
|
if glog.V(5) {
|
|
|
|
glog.V(5).Infof("defaultSink::Error(%v)", msg[:len(msg)-1])
|
2016-11-16 01:30:10 +01:00
|
|
|
}
|
2017-02-23 03:53:36 +01:00
|
|
|
fmt.Fprintf(d.writers[Error], msg)
|
|
|
|
d.counts[Error]++
|
2016-11-15 20:30:34 +01:00
|
|
|
}
|
|
|
|
|
2016-11-16 01:30:10 +01:00
|
|
|
func (d *defaultSink) Warningf(diag *Diag, args ...interface{}) {
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
msg := d.Stringify(Warning, diag, args...)
|
|
|
|
if glog.V(5) {
|
|
|
|
glog.V(5).Infof("defaultSink::Warning(%v)", msg[:len(msg)-1])
|
2016-11-16 01:30:10 +01:00
|
|
|
}
|
2017-02-23 03:53:36 +01:00
|
|
|
fmt.Fprintf(d.writers[Warning], msg)
|
|
|
|
d.counts[Warning]++
|
2016-11-15 20:30:34 +01:00
|
|
|
}
|
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
func (d *defaultSink) useColor(sev Severity) bool {
|
|
|
|
// we will use color so long as we're not spewing to debug (which is colorless).
|
|
|
|
return d.opts.Colors && sev != Debug
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *defaultSink) Stringify(sev Severity, diag *Diag, args ...interface{}) string {
|
2016-11-15 20:30:34 +01:00
|
|
|
var buffer bytes.Buffer
|
|
|
|
|
2017-02-10 02:26:49 +01:00
|
|
|
// First print the location if there is one.
|
2017-02-12 18:38:19 +01:00
|
|
|
if diag.Doc != nil || diag.Loc != nil {
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
buffer.WriteString(d.StringifyLocation(sev, diag.Doc, diag.Loc))
|
2016-11-15 20:30:34 +01:00
|
|
|
buffer.WriteString(": ")
|
2017-02-10 02:26:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now print the message category's prefix (error/warning).
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
if d.useColor(sev) {
|
|
|
|
switch sev {
|
2017-02-23 03:53:36 +01:00
|
|
|
case Info:
|
|
|
|
buffer.WriteString(colors.SpecInfo)
|
2017-02-10 02:26:49 +01:00
|
|
|
case Error:
|
2017-02-22 03:49:51 +01:00
|
|
|
buffer.WriteString(colors.SpecError)
|
2017-02-10 02:26:49 +01:00
|
|
|
case Warning:
|
2017-02-22 03:49:51 +01:00
|
|
|
buffer.WriteString(colors.SpecWarning)
|
2017-02-10 02:26:49 +01:00
|
|
|
default:
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
contract.Failf("Unrecognized diagnostic severity: %v", sev)
|
2017-02-10 02:26:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
buffer.WriteString(string(sev))
|
2017-02-10 02:26:49 +01:00
|
|
|
|
|
|
|
if diag.ID > 0 {
|
|
|
|
buffer.WriteString(" ")
|
|
|
|
buffer.WriteString(DefaultSinkIDPrefix)
|
|
|
|
buffer.WriteString(strconv.Itoa(int(diag.ID)))
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer.WriteString(": ")
|
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
if d.useColor(sev) {
|
Begin resource modeling and planning
This change introduces a new package, pkg/resource, that will form
the foundation for actually performing deployment plans and applications.
It contains the following key abstractions:
* resource.Provider is a wrapper around the CRUD operations exposed by
underlying resource plugins. It will eventually defer to resource.Plugin,
which itself defers -- over an RPC interface -- to the actual plugin, one
per package exposing resources. The provider will also understand how to
load, cache, and overall manage the lifetime of each plugin.
* resource.Resource is the actual resource object. This is created from
the overall evaluation object graph, but is simplified. It contains only
serializable properties, for example. Inter-resource references are
translated into serializable monikers as part of creating the resource.
* resource.Moniker is a serializable string that uniquely identifies
a resource in the Mu system. This is in contrast to resource IDs, which
are generated by resource providers and generally opaque to the Mu
system. See marapongo/mu#69 for more information about monikers and some
of their challenges (namely, designing a stable algorithm).
* resource.Snapshot is a "snapshot" taken from a graph of resources. This
is a transitive closure of state representing one possible configuration
of a given environment. This is what plans are created from. Eventually,
two snapshots will be diffable, in order to perform incremental updates.
One way of thinking about this is that a snapshot of the old world's state
is advanced, one step at a time, until it reaches a desired snapshot of
the new world's state.
* resource.Plan is a plan for carrying out desired CRUD operations on a target
environment. Each plan consists of zero-to-many Steps, each of which has
a CRUD operation type, a resource target, and a next step. This is an
enumerator because it is possible the plan will evolve -- and introduce new
steps -- as it is carried out (hence, the Next() method). At the moment, this
is linearized; eventually, we want to make this more "graph-like" so that we
can exploit available parallelism within the dependencies.
There are tons of TODOs remaining. However, the `mu plan` command is functioning
with these new changes -- including colorization FTW -- so I'm landing it now.
This is part of marapongo/mu#38 and marapongo/mu#41.
2017-02-17 21:31:48 +01:00
|
|
|
buffer.WriteString(colors.Reset)
|
2017-02-10 02:26:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, actually print the message itself.
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
if d.useColor(sev) {
|
2017-02-23 03:53:36 +01:00
|
|
|
buffer.WriteString(colors.SpecNote)
|
2016-11-15 20:30:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
buffer.WriteString(fmt.Sprintf(diag.Message, args...))
|
2017-02-10 02:26:49 +01:00
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
if d.useColor(sev) {
|
Begin resource modeling and planning
This change introduces a new package, pkg/resource, that will form
the foundation for actually performing deployment plans and applications.
It contains the following key abstractions:
* resource.Provider is a wrapper around the CRUD operations exposed by
underlying resource plugins. It will eventually defer to resource.Plugin,
which itself defers -- over an RPC interface -- to the actual plugin, one
per package exposing resources. The provider will also understand how to
load, cache, and overall manage the lifetime of each plugin.
* resource.Resource is the actual resource object. This is created from
the overall evaluation object graph, but is simplified. It contains only
serializable properties, for example. Inter-resource references are
translated into serializable monikers as part of creating the resource.
* resource.Moniker is a serializable string that uniquely identifies
a resource in the Mu system. This is in contrast to resource IDs, which
are generated by resource providers and generally opaque to the Mu
system. See marapongo/mu#69 for more information about monikers and some
of their challenges (namely, designing a stable algorithm).
* resource.Snapshot is a "snapshot" taken from a graph of resources. This
is a transitive closure of state representing one possible configuration
of a given environment. This is what plans are created from. Eventually,
two snapshots will be diffable, in order to perform incremental updates.
One way of thinking about this is that a snapshot of the old world's state
is advanced, one step at a time, until it reaches a desired snapshot of
the new world's state.
* resource.Plan is a plan for carrying out desired CRUD operations on a target
environment. Each plan consists of zero-to-many Steps, each of which has
a CRUD operation type, a resource target, and a next step. This is an
enumerator because it is possible the plan will evolve -- and introduce new
steps -- as it is carried out (hence, the Next() method). At the moment, this
is linearized; eventually, we want to make this more "graph-like" so that we
can exploit available parallelism within the dependencies.
There are tons of TODOs remaining. However, the `mu plan` command is functioning
with these new changes -- including colorization FTW -- so I'm landing it now.
This is part of marapongo/mu#38 and marapongo/mu#41.
2017-02-17 21:31:48 +01:00
|
|
|
buffer.WriteString(colors.Reset)
|
2017-02-10 02:26:49 +01:00
|
|
|
}
|
|
|
|
|
2016-11-15 20:30:34 +01:00
|
|
|
buffer.WriteRune('\n')
|
|
|
|
|
2017-05-18 20:38:28 +02:00
|
|
|
// TODO[pulumi/lumi#15]: support Clang-style expressive diagnostics. This would entail, for example, using the
|
2016-11-23 21:30:02 +01:00
|
|
|
// buffer within the target document, to demonstrate the offending line/column range of code.
|
2016-11-15 20:30:34 +01:00
|
|
|
|
2017-02-10 02:26:49 +01:00
|
|
|
s := buffer.String()
|
|
|
|
|
|
|
|
// If colorization was requested, compile and execute the directives now.
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
if d.useColor(sev) {
|
2017-02-28 19:32:24 +01:00
|
|
|
s = colors.ColorizeText(s)
|
2017-02-10 02:26:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return s
|
2016-11-15 20:30:34 +01:00
|
|
|
}
|
2017-02-12 18:38:19 +01:00
|
|
|
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
func (d *defaultSink) StringifyLocation(sev Severity, doc *Document, loc *Location) string {
|
2017-02-12 18:38:19 +01:00
|
|
|
var buffer bytes.Buffer
|
|
|
|
|
|
|
|
if doc != nil {
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
if d.useColor(sev) {
|
2017-02-22 03:49:51 +01:00
|
|
|
buffer.WriteString(colors.SpecLocation)
|
2017-02-12 18:38:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
file := doc.File
|
|
|
|
if d.opts.Pwd != "" {
|
|
|
|
// If a PWD is available, try to create a relative path.
|
|
|
|
rel, err := filepath.Rel(d.opts.Pwd, file)
|
|
|
|
if err == nil {
|
|
|
|
file = rel
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buffer.WriteString(file)
|
|
|
|
}
|
|
|
|
|
|
|
|
if loc != nil && !loc.IsEmpty() {
|
|
|
|
buffer.WriteRune('(')
|
|
|
|
buffer.WriteString(strconv.Itoa(loc.Start.Line))
|
|
|
|
buffer.WriteRune(',')
|
|
|
|
buffer.WriteString(strconv.Itoa(loc.Start.Column))
|
|
|
|
buffer.WriteRune(')')
|
|
|
|
}
|
|
|
|
|
|
|
|
var s string
|
|
|
|
if doc != nil || loc != nil {
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
if d.useColor(sev) {
|
Begin resource modeling and planning
This change introduces a new package, pkg/resource, that will form
the foundation for actually performing deployment plans and applications.
It contains the following key abstractions:
* resource.Provider is a wrapper around the CRUD operations exposed by
underlying resource plugins. It will eventually defer to resource.Plugin,
which itself defers -- over an RPC interface -- to the actual plugin, one
per package exposing resources. The provider will also understand how to
load, cache, and overall manage the lifetime of each plugin.
* resource.Resource is the actual resource object. This is created from
the overall evaluation object graph, but is simplified. It contains only
serializable properties, for example. Inter-resource references are
translated into serializable monikers as part of creating the resource.
* resource.Moniker is a serializable string that uniquely identifies
a resource in the Mu system. This is in contrast to resource IDs, which
are generated by resource providers and generally opaque to the Mu
system. See marapongo/mu#69 for more information about monikers and some
of their challenges (namely, designing a stable algorithm).
* resource.Snapshot is a "snapshot" taken from a graph of resources. This
is a transitive closure of state representing one possible configuration
of a given environment. This is what plans are created from. Eventually,
two snapshots will be diffable, in order to perform incremental updates.
One way of thinking about this is that a snapshot of the old world's state
is advanced, one step at a time, until it reaches a desired snapshot of
the new world's state.
* resource.Plan is a plan for carrying out desired CRUD operations on a target
environment. Each plan consists of zero-to-many Steps, each of which has
a CRUD operation type, a resource target, and a next step. This is an
enumerator because it is possible the plan will evolve -- and introduce new
steps -- as it is carried out (hence, the Next() method). At the moment, this
is linearized; eventually, we want to make this more "graph-like" so that we
can exploit available parallelism within the dependencies.
There are tons of TODOs remaining. However, the `mu plan` command is functioning
with these new changes -- including colorization FTW -- so I'm landing it now.
This is part of marapongo/mu#38 and marapongo/mu#41.
2017-02-17 21:31:48 +01:00
|
|
|
buffer.WriteString(colors.Reset)
|
2017-02-12 18:38:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
s = buffer.String()
|
|
|
|
|
|
|
|
// If colorization was requested, compile and execute the directives now.
|
Introduce an interface to read config
This change adds an engine gRPC interface, and associated implementation,
so that plugins may do interesting things that require "phoning home".
Previously, the engine would fire up plugins and talk to them directly,
but there was no way for a plugin to ask the engine to do anything.
The motivation here is so that plugins can read evaluator state, such
as config information, but this change also allows richer logging
functionality than previously possible. We will still auto-log any
stdout/stderr writes; however, explicit errors, warnings, informational,
and even debug messages may be written over the Log API.
2017-06-21 04:45:07 +02:00
|
|
|
if d.useColor(sev) {
|
2017-02-28 19:32:24 +01:00
|
|
|
s = colors.ColorizeText(s)
|
2017-02-12 18:38:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|