// 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.

syntax = "proto3";

import "plugin.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/struct.proto";

package pulumirpc;

// Analyzer provides a pluggable interface for checking resource definitions against some number of
// resource policies. It is intentionally open-ended, allowing for implementations that check
// everything from raw resource definitions to entire projects/stacks/snapshots for arbitrary
// issues -- style, policy, correctness, security, and so on.
service Analyzer {
    // Analyze analyzes a single resource object, and returns any errors that it finds.
    // Called with the "inputs" to the resource, before it is updated.
    rpc Analyze(AnalyzeRequest) returns (AnalyzeResponse) {}
    // AnalyzeStack analyzes all resources within a stack, at the end of a successful
    // preview or update. The provided resources are the "outputs", after any mutations
    // have taken place.
    rpc AnalyzeStack(AnalyzeStackRequest) returns (AnalyzeResponse) {}
    // GetAnalyzerInfo returns metadata about the analyzer (e.g., list of policies contained).
    rpc GetAnalyzerInfo(google.protobuf.Empty) returns (AnalyzerInfo) {}
    // GetPluginInfo returns generic information about this plugin, like its version.
    rpc GetPluginInfo(google.protobuf.Empty) returns (PluginInfo) {}
    // Configure configures the analyzer, passing configuration properties for each policy.
    rpc Configure(ConfigureAnalyzerRequest) returns (google.protobuf.Empty) {}
}

message AnalyzeRequest {
    string type = 1;                                                    // the type token of the resource.
    google.protobuf.Struct properties = 2;                              // the full properties to use for validation.
    string urn = 3;                                                     // the URN of the resource.
    string name = 4;                                                    // the name for the resource's URN.
    AnalyzerResourceOptions options = 5;                                // the resource options.
    AnalyzerProviderResource provider = 6;                              // the resource's provider.
}

// AnalyzerResource defines the view of a Pulumi-managed resource as sent to Analyzers. The properties
// of the resource are specific to the type of analysis being performed. See the Analyzer
// service definition for more information.
message AnalyzerResource {
    string type = 1;                                                    // the type token of the resource.
    google.protobuf.Struct properties = 2;                              // the full properties to use for validation.
    string urn = 3;                                                     // the URN of the resource.
    string name = 4;                                                    // the name for the resource's URN.
    AnalyzerResourceOptions options = 5;                                // the resource options.
    AnalyzerProviderResource provider = 6;                              // the resource's provider.
    string parent = 7;                                                  // an optional parent URN that this child resource belongs to.
    repeated string dependencies = 8;                                   // a list of URNs that this resource depends on.
    map<string, AnalyzerPropertyDependencies> propertyDependencies = 9; // a map from property keys to the dependencies of the property.
}

// AnalyzerResourceOptions defines the options associated with a resource.
message AnalyzerResourceOptions {
    // CustomTimeouts allows a user to be able to create a set of custom timeout parameters.
    message CustomTimeouts {
        double create = 1; // The create resource timeout in seconds.
        double update = 2; // The update resource timeout in seconds.
        double delete = 3; // The delete resource timeout in seconds.
    }

    bool protect = 1;                            // true if the resource should be marked protected.
    repeated string ignoreChanges = 2;           // a list of property names to ignore during changes.
    bool deleteBeforeReplace = 3;                // true if this resource should be deleted before replacement.
    bool deleteBeforeReplaceDefined = 4;         // true if the deleteBeforeReplace property should be treated as defined even if it is false.
    repeated string additionalSecretOutputs = 5; // a list of output properties that should also be treated as secret, in addition to ones we detect.
    repeated string aliases = 6;                 // a list of additional URNs that shoud be considered the same.
    CustomTimeouts customTimeouts = 7;           // a config block that will be used to configure timeouts for CRUD operations.
}

// AnalyzerProviderResource provides information about a resource's provider.
message AnalyzerProviderResource {
    string type = 1;                       // the type token of the resource.
    google.protobuf.Struct properties = 2; // the full properties to use for validation.
    string urn = 3;                        // the URN of the resource.
    string name = 4;                       // the name for the resource's URN.
}

// AnalyzerPropertyDependencies describes the resources that a particular property depends on.
message AnalyzerPropertyDependencies {
    repeated string urns = 1; // A list of URNs this property depends on.
}

message AnalyzeStackRequest {
    repeated AnalyzerResource resources = 1;
}

message AnalyzeResponse {
    repeated AnalyzeDiagnostic diagnostics = 2; // information about policy violations.
}

// EnforcementLevel indicates the severity of a policy violation.
enum EnforcementLevel {
    ADVISORY = 0;  // Displayed to users, but does not block deployment.
    MANDATORY = 1; // Stops deployment, cannot be overridden.
    DISABLED = 2;  // Disabled policies do not run during a deployment.
}

message AnalyzeDiagnostic {
    string policyName = 1;                 // Name of the violated policy.
    string policyPackName = 2;             // Name of the policy pack the policy is in.
    string policyPackVersion = 3;          // Version of the policy pack.
    string description = 4;                // Description of policy rule. e.g., "encryption enabled."
    string message = 5;                    // Message to display on policy violation, e.g., remediation steps.
    repeated string tags = 6;              // Keywords/terms to associate with a policy, e.g., "cost".
    EnforcementLevel enforcementLevel = 7; // Severity of the policy violation.
    string urn = 8;                        // URN of the resource that violates the policy.
}

// AnalyzerInfo provides metadata about a PolicyPack inside an analyzer.
message AnalyzerInfo {
    string name = 1;                             // Name of the PolicyPack.
    string displayName = 2;                      // Pretty name for the PolicyPack.
    repeated PolicyInfo policies = 3;            // Metadata about policies contained in PolicyPack.
    string version = 4;                          // Version of the Policy Pack.
    bool supportsConfig = 5;                     // Whether the Policy Pack supports config.
    map<string, PolicyConfig> initialConfig = 6; // Map of policy name to config.
}

// PolicyInfo provides metadata about a policy within a Policy Pack.
message PolicyInfo {
    string name = 1;                       // Name of the policy.
    string displayName = 2;                // Pretty name for the policy.
    string description = 3;                // Description of policy rule. e.g., "encryption enabled."
    string message = 4;                    // Message to display on policy violation, e.g., remediation steps.
    EnforcementLevel enforcementLevel = 5; // Severity of the policy violation.
    PolicyConfigSchema configSchema = 6;   // Config schema for the policy.
}

// PolicyConfigSchema provides the schema for a policy's configuration.
message PolicyConfigSchema {
    google.protobuf.Struct properties = 1; // JSON schema for each property.
    repeated string required = 2;          // Required properties.
}

// PolicyConfig provides configuration for a policy.
message PolicyConfig {
    EnforcementLevel enforcementLevel = 1; // Enforcement level of the policy.
    google.protobuf.Struct properties = 2; // Configuration properties of the policy.
}

// ConfigureAnalyzerRequest provides configuration information to the analyzer.
message ConfigureAnalyzerRequest {
    map<string, PolicyConfig> policyConfig = 1; // Map of policy name to config.
}
