Skip to content

Commit

Permalink
Serial port datasource (#3247) (#1860)
Browse files Browse the repository at this point in the history
* Add serial port datasource

* Add doc for serial port ds

* Serial port test

* Formatting

* Markdown fixes

* Remove pagination, we should always be able to retrieve 1MB

Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
modular-magician authored Mar 17, 2020
1 parent b873b76 commit ae50ddc
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/3247.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-datasource
`google_compute_instance_serial_port`
```
59 changes: 59 additions & 0 deletions google-beta/data_source_google_compute_instance_serial_port.go
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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)
}
1 change: 1 addition & 0 deletions google-beta/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
102 changes: 102 additions & 0 deletions website/docs/d/datasource_compute_instance_serial_port.html.markdown
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit ae50ddc

Please sign in to comment.