/*
 *
 * Copyright 2019 gRPC authors.
 *
 * 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 bootstrap provides the functionality to initialize certain aspects
// of an xDS client by reading a bootstrap file.
package bootstrap

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	v2corepb "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
	v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/google"
	"google.golang.org/grpc/xds/internal/version"
)

const (
	// Environment variable which holds the name of the xDS bootstrap file.
	bootstrapFileEnv = "GRPC_XDS_BOOTSTRAP"
	// Environment variable which controls the use of xDS v3 API.
	v3SupportEnv = "GRPC_XDS_EXPERIMENTAL_V3_SUPPORT"
	// The "server_features" field in the bootstrap file contains a list of
	// features supported by the server. A value of "xds_v3" indicates that the
	// server supports the v3 version of the xDS transport protocol.
	serverFeaturesV3 = "xds_v3"

	// Type name for Google default credentials.
	googleDefaultCreds              = "google_default"
	gRPCUserAgentName               = "gRPC Go"
	clientFeatureNoOverprovisioning = "envoy.lb.does_not_support_overprovisioning"
)

var gRPCVersion = fmt.Sprintf("%s %s", gRPCUserAgentName, grpc.Version)

// For overriding in unit tests.
var bootstrapFileReadFunc = ioutil.ReadFile

// Config provides the xDS client with several key bits of information that it
// requires in its interaction with an xDS server. The Config is initialized
// from the bootstrap file.
type Config struct {
	// BalancerName is the name of the xDS server to connect to.
	//
	// The bootstrap file contains a list of servers (with name+creds), but we
	// pick the first one.
	BalancerName string
	// Creds contains the credentials to be used while talking to the xDS
	// server, as a grpc.DialOption.
	Creds grpc.DialOption
	// TransportAPI indicates the API version of xDS transport protocol to use.
	// This describes the xDS gRPC endpoint and version of
	// DiscoveryRequest/Response used on the wire.
	TransportAPI version.TransportAPI
	// NodeProto contains the Node proto to be used in xDS requests. The actual
	// type depends on the transport protocol version used.
	NodeProto proto.Message
}

type channelCreds struct {
	Type   string          `json:"type"`
	Config json.RawMessage `json:"config"`
}

type xdsServer struct {
	ServerURI    string         `json:"server_uri"`
	ChannelCreds []channelCreds `json:"channel_creds"`
}

// NewConfig returns a new instance of Config initialized by reading the
// bootstrap file found at ${GRPC_XDS_BOOTSTRAP}.
//
// The format of the bootstrap file will be as follows:
// {
//    "xds_server": {
//      "server_uri": <string containing URI of xds server>,
//      "channel_creds": [
//        {
//          "type": <string containing channel cred type>,
//          "config": <JSON object containing config for the type>
//        }
//      ],
//      "server_features": [ ... ]
//    },
//    "node": <JSON form of Node proto>
// }
//
// Currently, we support exactly one type of credential, which is
// "google_default", where we use the host's default certs for transport
// credentials and a Google oauth token for call credentials.
//
// This function tries to process as much of the bootstrap file as possible (in
// the presence of the errors) and may return a Config object with certain
// fields left unspecified, in which case the caller should use some sane
// defaults.
func NewConfig() (*Config, error) {
	config := &Config{}

	fName, ok := os.LookupEnv(bootstrapFileEnv)
	if !ok {
		return nil, fmt.Errorf("xds: Environment variable %v not defined", bootstrapFileEnv)
	}
	logger.Infof("Got bootstrap file location from %v environment variable: %v", bootstrapFileEnv, fName)

	data, err := bootstrapFileReadFunc(fName)
	if err != nil {
		return nil, fmt.Errorf("xds: Failed to read bootstrap file %s with error %v", fName, err)
	}
	logger.Debugf("Bootstrap content: %s", data)

	var jsonData map[string]json.RawMessage
	if err := json.Unmarshal(data, &jsonData); err != nil {
		return nil, fmt.Errorf("xds: Failed to parse file %s (content %v) with error: %v", fName, string(data), err)
	}

	serverSupportsV3 := false
	m := jsonpb.Unmarshaler{AllowUnknownFields: true}
	for k, v := range jsonData {
		switch k {
		case "node":
			// We unconditionally convert the JSON into a v3.Node proto. The v3
			// proto does not contain the deprecated field "build_version" from
			// the v2 proto. We do not expect the bootstrap file to contain the
			// "build_version" field. In any case, the unmarshal will succeed
			// because we have set the `AllowUnknownFields` option on the
			// unmarshaler.
			n := &v3corepb.Node{}
			if err := m.Unmarshal(bytes.NewReader(v), n); err != nil {
				return nil, fmt.Errorf("xds: jsonpb.Unmarshal(%v) for field %q failed during bootstrap: %v", string(v), k, err)
			}
			config.NodeProto = n
		case "xds_servers":
			var servers []*xdsServer
			if err := json.Unmarshal(v, &servers); err != nil {
				return nil, fmt.Errorf("xds: json.Unmarshal(%v) for field %q failed during bootstrap: %v", string(v), k, err)
			}
			if len(servers) < 1 {
				return nil, fmt.Errorf("xds: bootstrap file parsing failed during bootstrap: file doesn't contain any xds server to connect to")
			}
			xs := servers[0]
			config.BalancerName = xs.ServerURI
			for _, cc := range xs.ChannelCreds {
				if cc.Type == googleDefaultCreds {
					config.Creds = grpc.WithCredentialsBundle(google.NewDefaultCredentials())
					// We stop at the first credential type that we support.
					break
				}
			}
		case "server_features":
			var features []string
			if err := json.Unmarshal(v, &features); err != nil {
				return nil, fmt.Errorf("xds: json.Unmarshal(%v) for field %q failed during bootstrap: %v", string(v), k, err)
			}
			for _, f := range features {
				switch f {
				case serverFeaturesV3:
					serverSupportsV3 = true
				}
			}
		}
		// Do not fail the xDS bootstrap when an unknown field is seen. This can
		// happen when an older version client reads a newer version bootstrap
		// file with new fields.
	}

	if config.BalancerName == "" {
		return nil, fmt.Errorf("xds: Required field %q not found in bootstrap", "xds_servers.server_uri")
	}

	// We end up using v3 transport protocol version only if the following
	// conditions are met:
	// 1. Server supports v3, indicated by the presence of "xds_v3" in
	//    server_features.
	// 2. Environment variable "GRPC_XDS_EXPERIMENTAL_V3_SUPPORT" is set to
	//    true.
	// The default value of the enum type "version.TransportAPI" is v2.
	//
	// TODO: there are multiple env variables, GRPC_XDS_BOOTSTRAP and
	// GRPC_XDS_EXPERIMENTAL_V3_SUPPORT. Move all env variables into a separate
	// package.
	if v3Env := os.Getenv(v3SupportEnv); v3Env == "true" {
		if serverSupportsV3 {
			config.TransportAPI = version.TransportV3
		}
	}

	if err := config.updateNodeProto(); err != nil {
		return nil, err
	}
	logger.Infof("Bootstrap config for creating xds-client: %+v", config)
	return config, nil
}

// updateNodeProto updates the node proto read from the bootstrap file.
//
// Node proto in Config contains a v3.Node protobuf message corresponding to the
// JSON contents found in the bootstrap file. This method performs some post
// processing on it:
// 1. If we don't find a nodeProto in the bootstrap file, we create an empty one
// here. That way, callers of this function can always expect that the NodeProto
// field is non-nil.
// 2. If the transport protocol version to be used is not v3, we convert the
// current v3.Node proto in a v2.Node proto.
// 3. Some additional fields which are not expected to be set in the bootstrap
// file are populated here.
func (c *Config) updateNodeProto() error {
	if c.TransportAPI == version.TransportV3 {
		v3, _ := c.NodeProto.(*v3corepb.Node)
		if v3 == nil {
			v3 = &v3corepb.Node{}
		}
		v3.UserAgentName = gRPCUserAgentName
		v3.UserAgentVersionType = &v3corepb.Node_UserAgentVersion{UserAgentVersion: grpc.Version}
		v3.ClientFeatures = append(v3.ClientFeatures, clientFeatureNoOverprovisioning)
		c.NodeProto = v3
		return nil
	}

	v2 := &v2corepb.Node{}
	if c.NodeProto != nil {
		v3, err := proto.Marshal(c.NodeProto)
		if err != nil {
			return fmt.Errorf("xds: proto.Marshal(%v): %v", c.NodeProto, err)
		}
		if err := proto.Unmarshal(v3, v2); err != nil {
			return fmt.Errorf("xds: proto.Unmarshal(%v): %v", v3, err)
		}
	}
	c.NodeProto = v2

	// BuildVersion is deprecated, and is replaced by user_agent_name and
	// user_agent_version. But the management servers are still using the old
	// field, so we will keep both set.
	v2.BuildVersion = gRPCVersion
	v2.UserAgentName = gRPCUserAgentName
	v2.UserAgentVersionType = &v2corepb.Node_UserAgentVersion{UserAgentVersion: grpc.Version}
	v2.ClientFeatures = append(v2.ClientFeatures, clientFeatureNoOverprovisioning)
	return nil
}
