diff --git a/.changelog/3247.txt b/.changelog/3247.txt new file mode 100644 index 0000000000..f5d9b5449a --- /dev/null +++ b/.changelog/3247.txt @@ -0,0 +1,3 @@ +```release-note:new-datasource +`google_compute_instance_serial_port` +``` diff --git a/google-beta/data_source_google_compute_instance_serial_port.go b/google-beta/data_source_google_compute_instance_serial_port.go new file mode 100644 index 0000000000..365b93fecf --- /dev/null +++ b/google-beta/data_source_google_compute_instance_serial_port.go @@ -0,0 +1,59 @@ +package google + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceGoogleComputeInstanceSerialPort() *schema.Resource { + return &schema.Resource{ + Read: computeInstanceSerialPortRead, + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Required: true, + }, + "instance": { + Type: schema.TypeString, + Required: true, + }, + "zone": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "contents": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func computeInstanceSerialPortRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + d.Set("project", project) + zone, err := getZone(d, config) + if err != nil { + return err + } + d.Set("zone", zone) + + port := int64(d.Get("port").(int)) + output, err := config.clientCompute.Instances.GetSerialPortOutput(project, zone, d.Get("instance").(string)).Port(port).Do() + if err != nil { + return err + } + + d.Set("contents", output.Contents) + d.SetId(output.SelfLink) + return nil +} diff --git a/google-beta/data_source_google_compute_instance_serial_port_test.go b/google-beta/data_source_google_compute_instance_serial_port_test.go new file mode 100644 index 0000000000..c11eb62da4 --- /dev/null +++ b/google-beta/data_source_google_compute_instance_serial_port_test.go @@ -0,0 +1,81 @@ +package google + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccDataSourceComputeInstanceSerialPort_basic(t *testing.T) { + instanceName := fmt.Sprintf("tf-test-serial-data-%s", acctest.RandString(10)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceSerialPort(instanceName), + Check: resource.ComposeTestCheckFunc( + // Contents of serial port output include lots of initialization logging + resource.TestMatchResourceAttr("data.google_compute_instance_serial_port.serial", "contents", + regexp.MustCompile("Initializing cgroup subsys")), + ), + }, + }, + }) +} + +func testAccComputeInstanceSerialPort(instanceName string) string { + return fmt.Sprintf(` +resource "google_compute_instance" "default" { + name = "%s" + machine_type = "n1-standard-1" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = "debian-8-jessie-v20160803" + } + } + + // Local SSD disk + scratch_disk { + interface = "SCSI" + } + + network_interface { + network = "default" + + access_config { + // Ephemeral IP + } + } + + metadata = { + foo = "bar" + serial-port-logging-enable = "TRUE" + windows-keys = jsonencode( + { + email = "example.user@example.com" + expireOn = "2020-04-14T01:37:19Z" + exponent = "AQAB" + modulus = "wgsquN4IBNPqIUnu+h/5Za1kujb2YRhX1vCQVQAkBwnWigcCqOBVfRa5JoZfx6KIvEXjWqa77jPvlsxM4WPqnDIM2qiK36up3SKkYwFjff6F2ni/ry8vrwXCX3sGZ1hbIHlK0O012HpA3ISeEswVZmX2X67naOvJXfY5v0hGPWqCADao+xVxrmxsZD4IWnKl1UaZzI5lhAzr8fw6utHwx1EZ/MSgsEki6tujcZfN+GUDRnmJGQSnPTXmsf7Q4DKreTZk49cuyB3prV91S0x3DYjCUpSXrkVy1Ha5XicGD/q+ystuFsJnrrhbNXJbpSjM6sjo/aduAkZJl4FmOt0R7Q==" + userName = "example-user" + } + ) + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} + +data "google_compute_instance_serial_port" "serial" { + instance = google_compute_instance.default.name + zone = google_compute_instance.default.zone + port = 1 +} +`, instanceName) +} diff --git a/google-beta/provider.go b/google-beta/provider.go index b2de5e6a46..85b2b74450 100644 --- a/google-beta/provider.go +++ b/google-beta/provider.go @@ -506,6 +506,7 @@ func Provider() terraform.ResourceProvider { "google_compute_global_address": dataSourceGoogleComputeGlobalAddress(), "google_compute_image": dataSourceGoogleComputeImage(), "google_compute_instance": dataSourceGoogleComputeInstance(), + "google_compute_instance_serial_port": dataSourceGoogleComputeInstanceSerialPort(), "google_compute_instance_group": dataSourceGoogleComputeInstanceGroup(), "google_compute_lb_ip_ranges": dataSourceGoogleComputeLbIpRanges(), "google_compute_network": dataSourceGoogleComputeNetwork(), diff --git a/website/docs/d/datasource_compute_instance_serial_port.html.markdown b/website/docs/d/datasource_compute_instance_serial_port.html.markdown new file mode 100644 index 0000000000..fa3ce11053 --- /dev/null +++ b/website/docs/d/datasource_compute_instance_serial_port.html.markdown @@ -0,0 +1,102 @@ +--- +subcategory: "Compute Engine" +layout: "google" +page_title: "Google: google_compute_instance_serial_port" +sidebar_current: "docs-google-datasource-compute-instance-serial-port" +description: |- + Get the serial port output from a Compute Instance. +--- + +# google\_compute\_instance\_serial\_port + +Get the serial port output from a Compute Instance. For more information see +the official [API](https://cloud.google.com/compute/docs/instances/viewing-serial-port-output) documentation. + +## Example Usage + +```hcl +data "google_compute_instance_serial_port" "serial" { + instance = "my-instance" + zone = "us-central1-a" + port = 1 +} + +output "serial_out" { + value = data.google_compute_instance_serial_port.serial.contents +} +``` + +Using the serial port output to generate a windows password, derived from the [official guide](https://cloud.google.com/compute/docs/instances/windows/automate-pw-generation): + +```hcl +resource "google_compute_instance" "windows" { + name = "windows-instance" + machine_type = "n1-standard-1" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = "gce-uefi-images/windows-2019" + } + } + + network_interface { + network = "default" + + access_config { + // Ephemeral IP + } + } + + metadata = { + serial-port-logging-enable = "TRUE" + // Derived from https://cloud.google.com/compute/docs/instances/windows/automate-pw-generation + windows-keys = jsonencode( + { + email = "example.user@example.com" + expireOn = "2020-04-14T01:37:19Z" + exponent = "AQAB" + modulus = "wgsquN4IBNPqIUnu+h/5Za1kujb2YRhX1vCQVQAkBwnWigcCqOBVfRa5JoZfx6KIvEXjWqa77jPvlsxM4WPqnDIM2qiK36up3SKkYwFjff6F2ni/ry8vrwXCX3sGZ1hbIHlK0O012HpA3ISeEswVZmX2X67naOvJXfY5v0hGPWqCADao+xVxrmxsZD4IWnKl1UaZzI5lhAzr8fw6utHwx1EZ/MSgsEki6tujcZfN+GUDRnmJGQSnPTXmsf7Q4DKreTZk49cuyB3prV91S0x3DYjCUpSXrkVy1Ha5XicGD/q+ystuFsJnrrhbNXJbpSjM6sjo/aduAkZJl4FmOt0R7Q==" + userName = "example-user" + } + ) + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} + +data "google_compute_instance_serial_port" "serial" { + instance = google_compute_instance.windows.name + zone = google_compute_instance.windows.zone + port = 4 +} + +output "serial_out" { + value = data.google_compute_instance_serial_port.serial.contents +} +``` + +## Argument Reference + +The following arguments are supported: + +* `instance` - (Required) The name of the Compute Instance to read output from. + +* `port` - (Required) The number of the serial port to read output from. Possible values are 1-4. + +- - - + +* `project` - (Optional) The project in which the Compute Instance exists. If it + is not provided, the provider project is used. + +* `zone` - (Optional) The zone in which the Compute Instance exists. + If it is not provided, the provider zone is used. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are +exported: + +* `contents` - The output of the serial port. Serial port output is available only when the VM instance is running, and logs are limited to the most recent 1 MB of output per port.