// Copyright 2024 Google LLC
//
// 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";

package google.cloud.osconfig.agentendpoint.v1;

option go_package = "cloud.google.com/go/osconfig/agentendpoint/apiv1/agentendpointpb;agentendpointpb";
option java_outer_classname = "PatchJobs";
option java_package = "com.google.cloud.osconfig.agentendpoint.v1";

// Patch configuration specifications. Contains details on how to
// apply patches to a VM instance.
message PatchConfig {
  // Post-patch reboot settings.
  enum RebootConfig {
    // The default behavior is DEFAULT.
    REBOOT_CONFIG_UNSPECIFIED = 0;

    // The agent decides if a reboot is necessary by checking
    // signals such as registry keys on Windows or `/var/run/reboot-required` on
    // APT based systems. On RPM based systems, a set of core system package
    // install times are compared with system boot time.
    DEFAULT = 1;

    // Always reboot the machine after the update completes.
    ALWAYS = 2;

    // Never reboot the machine after the update completes.
    NEVER = 3;
  }

  // Post-patch reboot settings.
  RebootConfig reboot_config = 1;

  // Retry strategy can be defined to have the agent retry patching
  // during the window if patching fails. If omitted, the agent will use its
  // default retry strategy.
  RetryStrategy retry_strategy = 2;

  // Apt update settings. Use this override the default apt patch rules.
  AptSettings apt = 3;

  // Yum update settings. Use this override the default yum patch rules.
  YumSettings yum = 4;

  // Goo update settings. Use this override the default goo patch rules.
  GooSettings goo = 5;

  // Zypper update settings. Use this override the default zypper patch rules.
  ZypperSettings zypper = 6;

  // Windows update settings. Use this override the default windows patch rules.
  WindowsUpdateSettings windows_update = 7;

  // The ExecStep to run before the patch update.
  ExecStep pre_step = 8;

  // The ExecStep to run after the patch update.
  ExecStep post_step = 9;

  // Allows the patch job to run on Managed instance groups (MIGs).
  bool mig_instances_allowed = 10;
}

// Apt patching will be performed by executing `apt-get update && apt-get
// upgrade`. Additional options can be set to control how this is executed.
message AptSettings {
  // Apt patch type.
  enum Type {
    // By default, upgrade will be performed.
    TYPE_UNSPECIFIED = 0;

    // Runs `apt-get dist-upgrade`.
    DIST = 1;

    // Runs `apt-get upgrade`.
    UPGRADE = 2;
  }

  // By changing the type to DIST, the patching will be performed
  // using `apt-get dist-upgrade` instead.
  Type type = 1;

  // List of packages to exclude from update.
  repeated string excludes = 2;

  // An exclusive list of packages to be updated. These are the only packages
  // that will be updated. If these packages are not installed, they will be
  // ignored. This field cannot be specified with any other patch configuration
  // fields.
  repeated string exclusive_packages = 3;
}

// Yum patching will be performed by executing `yum update`. Additional options
// can be set to control how this is executed.
//
// Note that not all settings are supported on all platforms.
message YumSettings {
  // Adds the `--security` flag to `yum update`. Not supported on
  // all platforms.
  bool security = 1;

  // Will cause patch to run `yum update-minimal` instead.
  bool minimal = 2;

  // List of packages to exclude from update. These packages will be excluded by
  // using the yum `--exclude` flag.
  repeated string excludes = 3;

  // An exclusive list of packages to be updated. These are the only packages
  // that will be updated. If these packages are not installed, they will be
  // ignored. This field must not be specified with any other patch
  // configuration fields.
  repeated string exclusive_packages = 4;
}

// Googet patching is performed by running `googet update`.
message GooSettings {}

// Zypper patching is performed by running `zypper patch`.
// See also https://en.opensuse.org/SDB:Zypper_manual.
message ZypperSettings {
  // Adds the `--with-optional` flag to `zypper patch`.
  bool with_optional = 1;

  // Adds the `--with-update` flag, to `zypper patch`.
  bool with_update = 2;

  // Install only patches with these categories.
  // Common categories include security, recommended, and feature.
  repeated string categories = 3;

  // Install only patches with these severities.
  // Common severities include critical, important, moderate, and low.
  repeated string severities = 4;

  // List of patches to exclude from update.
  repeated string excludes = 5;

  // An exclusive list of patches to be updated. These are the only patches
  // that will be installed using 'zypper patch patch:<patch_name>' command.
  // This field must not be used with any other patch configuration fields.
  repeated string exclusive_patches = 6;
}

// Windows patching is performed using the Windows Update Agent.
message WindowsUpdateSettings {
  // Microsoft Windows update classifications as defined in
  // [1]
  // https://support.microsoft.com/en-us/help/824684/description-of-the-standard-terminology-that-is-used-to-describe-micro
  enum Classification {
    // Invalid. If classifications are included, they must be specified.
    CLASSIFICATION_UNSPECIFIED = 0;

    // "A widely released fix for a specific problem that addresses a critical,
    // non-security-related bug." [1]
    CRITICAL = 1;

    // "A widely released fix for a product-specific, security-related
    // vulnerability. Security vulnerabilities are rated by their severity. The
    // severity rating is indicated in the Microsoft security bulletin as
    // critical, important, moderate, or low." [1]
    SECURITY = 2;

    // "A widely released and frequent software update that contains additions
    // to a product’s definition database. Definition databases are often used
    // to detect objects that have specific attributes, such as malicious code,
    // phishing websites, or junk mail." [1]
    DEFINITION = 3;

    // "Software that controls the input and output of a device." [1]
    DRIVER = 4;

    // "New product functionality that is first distributed outside the context
    // of a product release and that is typically included in the next full
    // product release." [1]
    FEATURE_PACK = 5;

    // "A tested, cumulative set of all hotfixes, security updates, critical
    // updates, and updates. Additionally, service packs may contain additional
    // fixes for problems that are found internally since the release of the
    // product. Service packs my also contain a limited number of
    // customer-requested design changes or features." [1]
    SERVICE_PACK = 6;

    // "A utility or feature that helps complete a task or set of tasks." [1]
    TOOL = 7;

    // "A tested, cumulative set of hotfixes, security updates, critical
    // updates, and updates that are packaged together for easy deployment. A
    // rollup generally targets a specific area, such as security, or a
    // component of a product, such as Internet Information Services (IIS)." [1]
    UPDATE_ROLLUP = 8;

    // "A widely released fix for a specific problem. An update addresses a
    // noncritical, non-security-related bug." [1]
    UPDATE = 9;
  }

  // Only apply updates of these windows update classifications. If empty, all
  // updates will be applied.
  repeated Classification classifications = 1;

  // List of KBs to exclude from update.
  repeated string excludes = 2;

  // An exclusive list of kbs to be updated. These are the only patches
  // that will be updated. This field must not be used with other
  // patch configurations.
  repeated string exclusive_patches = 3;
}

// The strategy for retrying failed patches during the patch window.
message RetryStrategy {
  // If true, the agent will continue to try and patch until the window has
  // ended.
  bool enabled = 1;
}

// A step that runs an executable for a PatchJob.
message ExecStep {
  // The ExecStepConfig for all Linux VMs targeted by the PatchJob.
  ExecStepConfig linux_exec_step_config = 1;

  // The ExecStepConfig for all Windows VMs targeted by the PatchJob.
  ExecStepConfig windows_exec_step_config = 2;
}

// Common configurations for an ExecStep.
message ExecStepConfig {
  // The interpreter used to run the file.
  enum Interpreter {
    // If the interpreter is not specified, the value defaults to `NONE`.
    INTERPRETER_UNSPECIFIED = 0;

    // Indicates that the file is run as follows on each operating system:
    // + For Linux VMs, the file is ran as an executable and the interpreter
    // might be parsed from the [shebang
    // line](https://wikipedia.org/wiki/Shebang_(Unix)) of the file.
    // + For Windows VM, this value is not supported.
    NONE = 3;

    // Indicates that the file is run with `/bin/sh` on Linux and `cmd`
    // on Windows.
    SHELL = 1;

    // Indicates that the file is run with PowerShell.
    POWERSHELL = 2;
  }

  // Location of the executable.
  oneof executable {
    // An absolute path to the executable on the VM.
    string local_path = 1;

    // A GCS object containing the executable.
    GcsObject gcs_object = 2;
  }

  // Defaults to [0]. A list of possible return values that the
  // execution can return to indicate a success.
  repeated int32 allowed_success_codes = 3;

  // The script interpreter to use to run the script. If no interpreter is
  // specified the script will be executed directly, which will likely
  // only succeed for scripts with shebang lines.
  // [Wikipedia shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)).
  Interpreter interpreter = 4;
}

// GCS object representation.
message GcsObject {
  // Bucket of the GCS object.
  string bucket = 1;

  // Name of the GCS object.
  string object = 2;

  // Generation number of the GCS object. This is used to ensure that the
  // ExecStep specified by this PatchJob does not change.
  int64 generation_number = 3;
}
