Several users reported cases where error messages would cause a panic if they contained accented characters. I wasn't able to reproduce this failure locally, but tracked down the panic to logging gRPC calls. The Message field is typed as a string, which requires all of the characters to be valid UTF-8. This change runs each log string through the strings.ToValidUTF8 function, which will replace any invalid characters with the "unknown" character. This should prevent the the logger from panicking.
95 lines
2.9 KiB
Go
95 lines
2.9 KiB
Go
// Copyright 2016-2018, Pulumi Corporation.
|
||
//
|
||
// Licensed 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.
|
||
|
||
package provider
|
||
|
||
import (
|
||
"strings"
|
||
|
||
"github.com/pulumi/pulumi/sdk/v2/go/common/diag"
|
||
"github.com/pulumi/pulumi/sdk/v2/go/common/resource"
|
||
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
|
||
"github.com/pulumi/pulumi/sdk/v2/go/common/util/rpcutil"
|
||
lumirpc "github.com/pulumi/pulumi/sdk/v2/proto/go"
|
||
"golang.org/x/net/context"
|
||
"google.golang.org/grpc"
|
||
)
|
||
|
||
// HostClient is a client interface into the host's engine RPC interface.
|
||
type HostClient struct {
|
||
conn *grpc.ClientConn
|
||
client lumirpc.EngineClient
|
||
}
|
||
|
||
// NewHostClient dials the target address, connects over gRPC, and returns a client interface.
|
||
func NewHostClient(addr string) (*HostClient, error) {
|
||
conn, err := grpc.Dial(
|
||
addr,
|
||
grpc.WithInsecure(),
|
||
grpc.WithUnaryInterceptor(rpcutil.OpenTracingClientInterceptor()),
|
||
rpcutil.GrpcChannelOptions(),
|
||
)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &HostClient{
|
||
conn: conn,
|
||
client: lumirpc.NewEngineClient(conn),
|
||
}, nil
|
||
}
|
||
|
||
// Close closes and renders the connection and client unusable.
|
||
func (host *HostClient) Close() error {
|
||
return host.conn.Close()
|
||
}
|
||
|
||
func (host *HostClient) log(
|
||
context context.Context, sev diag.Severity, urn resource.URN, msg string, ephemeral bool,
|
||
) error {
|
||
var rpcsev lumirpc.LogSeverity
|
||
switch sev {
|
||
case diag.Debug:
|
||
rpcsev = lumirpc.LogSeverity_DEBUG
|
||
case diag.Info:
|
||
rpcsev = lumirpc.LogSeverity_INFO
|
||
case diag.Warning:
|
||
rpcsev = lumirpc.LogSeverity_WARNING
|
||
case diag.Error:
|
||
rpcsev = lumirpc.LogSeverity_ERROR
|
||
default:
|
||
contract.Failf("Unrecognized log severity type: %v", sev)
|
||
}
|
||
_, err := host.client.Log(context, &lumirpc.LogRequest{
|
||
Severity: rpcsev,
|
||
Message: strings.ToValidUTF8(msg, "<22>"),
|
||
Urn: string(urn),
|
||
Ephemeral: ephemeral,
|
||
})
|
||
return err
|
||
}
|
||
|
||
// Log logs a global message, including errors and warnings.
|
||
func (host *HostClient) Log(
|
||
context context.Context, sev diag.Severity, urn resource.URN, msg string,
|
||
) error {
|
||
return host.log(context, sev, urn, msg, false)
|
||
}
|
||
|
||
// LogStatus logs a global status message, including errors and warnings. Status messages will
|
||
// appear in the `Info` column of the progress display, but not in the final output.
|
||
func (host *HostClient) LogStatus(
|
||
context context.Context, sev diag.Severity, urn resource.URN, msg string,
|
||
) error {
|
||
return host.log(context, sev, urn, msg, true)
|
||
}
|