Giter Site home page Giter Site logo

equinix / terraform-provider-metal Goto Github PK

View Code? Open in Web Editor NEW
14.0 13.0 13.0 14.16 MB

DEPRECATED Equinix Metal standalone TF provider. Use the unified Equinix Terraform Provider.

Home Page: https://registry.terraform.io/providers/equinix/equinix/latest/docs/guides/migration_guide_equinix_metal

License: Mozilla Public License 2.0

Makefile 0.59% Go 98.92% Shell 0.48%
terraform terraform-provider packet equinix-metal equinix

terraform-provider-metal's Introduction

Equinix Metal Terraform Provider

End of Life GitHub release Go Report Card

Slack Twitter Follow

This repository is now End of Life meaning that this software is no longer supported nor maintained by Equinix Metal or its community.

Please review the Metal to Equinix provider migration guide. A guide is also available for migrating from the Packet provider.

The Equinix provider has full support for existing Terraform managed Metal resources once Terraform configuration and state are adapted. The Equinix provider manages resources including Network Edge and Fabric in addition to Metal.

See https://registry.terraform.io/providers/equinix/metal/latest/docs for documentation on the resources included in this deprecated provider.

terraform-provider-metal's People

Contributors

ayudemura avatar betawaffle avatar bflad avatar bzub avatar cole-h avatar ctreatma avatar displague avatar f440 avatar grahamc avatar grubernaut avatar jefferai avatar johnstudarus avatar kavu avatar ksatirli avatar miouge1 avatar miry avatar nicolai86 avatar normanjoyner avatar nurfet-becirevic avatar ocobles avatar paultyng avatar pshima avatar radeksimko avatar rainleander avatar rawkode avatar smintz avatar stack72 avatar t0mk avatar tchan2 avatar tombuildsstuff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terraform-provider-metal's Issues

Documentation is missing information

Hi!

I wondered long enough to just look into the Provider itself.

https://github.com/equinix/terraform-provider-metal/blob/main/metal/resource_metal_spot_market_request.go#L50

There are so many instance parameters that are just not on the documentation.
https://registry.terraform.io/providers/equinix/metal/latest/docs/resources/spot_market_request

I think some folks that are not that Terraform battle proof, like me, would like to have a documentation that reflects whats actually possible with the Terraform Provider.

Thanks!
Tobias

crash when importing resource metal_virtual_circuit

❯ terraform import metal_virtual_circuit.connection_attachment uuid
metal_virtual_circuit.connection_attachment: Importing from ID "uuid"...
metal_virtual_circuit.connection_attachment: Import prepared!
  Prepared metal_virtual_circuit for import
metal_virtual_circuit.connection_attachment: Refreshing state... [id=uuid]
╷
│ Error: Plugin did not respond
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ReadResource call. The plugin logs may contain more details.
╵

 


Stack trace from the terraform-provider-metal_v2.1.0 plugin:

 

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x18d03b8]

 

goroutine 81 [running]:
github.com/equinix/terraform-provider-metal/metal.resourceMetalVirtualCircuitRead(0xc0003284d0, 0x19d8080, 0xc000528500, 0xc0003284d0, 0x0)
        github.com/equinix/terraform-provider-metal/metal/resource_metal_virtual_circuit.go:134 +0x2d8
github.com/hashicorp/terraform-plugin-sdk/helper/schema.(*Resource).RefreshWithoutUpgrade(0xc00050fb00, 0xc000092b90, 0x19d8080, 0xc000528500, 0xc000326120, 0x0, 0x0)
        github.com/hashicorp/[email protected]/helper/schema/resource.go:455 +0x12e
github.com/hashicorp/terraform-plugin-sdk/internal/helper/plugin.(*GRPCProviderServer).ReadResource(0xc000508100, 0x1c0e290, 0xc0003fcf90, 0xc0000929b0, 0xc000508100, 0xc0003fcf90, 0xc0005c3a50)
        github.com/hashicorp/[email protected]/internal/helper/plugin/grpc_provider.go:525 +0x3dd
github.com/hashicorp/terraform-plugin-sdk/internal/tfplugin5._Provider_ReadResource_Handler(0x1a74460, 0xc000508100, 0x1c0e290, 0xc0003fcf90, 0xc000500840, 0x0, 0x1c0e290, 0xc0003fcf90, 0xc000314180, 0xb3)
        github.com/hashicorp/[email protected]/internal/tfplugin5/tfplugin5.pb.go:3153 +0x214
google.golang.org/grpc.(*Server).processUnaryRPC(0xc0000cc000, 0x1c16478, 0xc000602480, 0xc000310000, 0xc00009d620, 0x20e3e70, 0x0, 0x0, 0x0)
        google.golang.org/[email protected]/server.go:995 +0x482
google.golang.org/grpc.(*Server).handleStream(0xc0000cc000, 0x1c16478, 0xc000602480, 0xc000310000, 0x0)
        google.golang.org/[email protected]/server.go:1275 +0xd2c
google.golang.org/grpc.(*Server).serveStreams.func1.1(0xc0003fa000, 0xc0000cc000, 0x1c16478, 0xc000602480, 0xc000310000)
        google.golang.org/[email protected]/server.go:710 +0xab
created by google.golang.org/grpc.(*Server).serveStreams.func1
        google.golang.org/[email protected]/server.go:708 +0xa5

Error: The terraform-provider-metal_v2.1.0 plugin crashed!

Reported by @christianhxc

no way to lookup ip reservation ids

When consuming reservation ids, in a device's ip_address block, the reservation id is a needed field.

It is not currently possible to get the reservation id of an existing reservation.

Perhaps ip_block_ranges should return a structure that includes both the reservation id and the range.

Alternatively, a new ip_reservation datasource could provide this functionality. Lookups could be by IP Address + Project + Type.

Here is an example of how this could be used:

provider "dns" {}
provider "metal" {}

data "dns_a_record_set" "www" {
  host = "www.example.com"
}

data "metal_reserved_ip_block" "www" {
  project_id = "${var.existing_project}" // required?
  address = data.dns_a_record_set.www.addrs[0] // matches any reservation whose cidr contains this address (optional?)
  // cidr = "" // matches by cidr (optional filter?)
  // type = "public_ipv4" (optional filter?)
  // facility, metro (optional?)

  // error if multiple records match after all filters are applied?
}

resource "metal_device" "www" {
  ip_address {
    type = "public_ipv4"
     // is this an array or a string? docs need updating, they say string but the field is plural  
    reservation_ids = data.metal_reserved_ip_block.www.id  
  }
}

Attributes would include everything reported by a metal_reserved_ip_block resource.

Internal Validation errors after sdk v2 merge

        Error: InternalValidate
        
        Internal validation of the provider failed! This is always a bug
        with the provider itself, and not a user issue. Please report
        this bug:
        
        5 errors occurred:
        	* data source metal_facility: metro: StateFunc is extraneous, value should
        just be changed before setting on computed-only field
        	* data source metal_device: metro: StateFunc is extraneous, value should just
        be changed before setting on computed-only field
        	* data source metal_reserved_ip_block: metro: StateFunc is extraneous, value
        should just be changed before setting on computed-only field
        	* data source metal_connection: metro: StateFunc is extraneous, value should
        just be changed before setting on computed-only field
        	* data source metal_spot_market_request: metro: StateFunc is extraneous,
        value should just be changed before setting on computed-only field

User-Agent does not report Terraform

This has come up before and was thought to be corrected, but it is clear that the User-Agent being reported is currently incorrect. The reported User-Agent is not being set (https://github.com/equinix/terraform-provider-metal/blob/main/metal/config.go#L61).

TF_LOG=debug PACKNGO_DEBUG=1 terraform apply
terraform-provider-metal_v1.0.0: ---[ REQUEST ]---------------------------------------
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: POST /metal/v1/projects/.../ssh-keys HTTP/1.1
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: Host: api.equinix.com
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: User-Agent: packngo/0.5.1
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: Connection: close
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: Content-Length: 769
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: Accept: application/json
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: Content-Type: application/json
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: X-Auth-Token: ...
2021-01-28T17:10:39.216-0500 [DEBUG] plugin.terraform-provider-metal_v1.0.0: X-Consumer-Token: aZ9GmqHTPtxevv

metal_port_vlan_attachment doesn't work with metro

metal_port_vlan_attachment resource lists all vlans in a project to find a vlan by vxlan. It checks facilities. When using metro, the resource creation fails.

I found this out while wokring on equinix/terraform-provider-equinix#194

Culprit code:
https://github.com/equinix/terraform-provider-metal/blob/main/metal/resource_metal_port_vlan_attachment.go#L106

I think just the removal of the facility check should fix it. VXLAN must be unique in a project anyway.

HCL to invoke:

resource "metal_device" "web1" {
  hostname         = "web1"
  plan             = "c3.medium.x86"
  metro            = "sv"
  operating_system = "ubuntu_16_04"
  billing_cycle    = "hourly"
  project_id       = local.project_id
}


resource "metal_port_vlan_attachment" "test" {
  device_id = metal_device.web1.id
  port_name = "bond0"
  vlan_vnid = metal_vlan.test.vxlan
}

resource "metal_vlan" "test" {
  project_id       = local.project_id
  metro             = "sv"
  vxlan = 1215
  description       = "ffdfsdf"
}

Limited Collaborator Role testing

A new team member role is being introduced called "Limited Collaborator". This role is effectively the same as the Collaborator role but does not have access to pricing details.

The notable omission of pricing fields in response structures could potentially trigger errors in the TF provider. We should fix any errors in using Terraform with this membership type and document a temporary lack of support for this membership type, if needed, and update field documentation to detail where the collaborator type will change the expected response.

Related to equinix/terraform-provider-equinix#175

test failure: sweepers should unlock volumes before deleting

We should unlock volumes before attempting to delete them.

I suspect the API behavior has changed in some way and this error is surfacing as a side-effect. The result is that our projects are not being fully swept because volumes are not being swept.

2021/02/12 16:46:12 [ERR] error running (metal_device): Error deleting volume DELETE https://api.equinix.com/metal/v1/storage/c15e6abe-7e36-4f7f-b5dd-1ae339dfb393: 422 Cannot delete a locked item

Create a metal_hardware_reservation data source

There is currently no way to access a matching hardware reservation record in the TF provider. What criteria should be permitted aside from hardware_reservation_id?

It should also be possible to query metal_devices by hardware_reservation_id.

metal_facility data source should support filtering by feature flags

Module authors that want to enforce facility compatibility with their modules may benefit from feature flag filtering in the facility data source.

For example:

data "metal_facility" "hybrid_bonded_check" {
    code = var.facility
    features = ["ibx"] // all features selected must be present to match the facility
}

This resource would catch a mis-configuration created by choosing an invalid facility for a configuration that requires hybrid-bonded interfaces. The error message would not be very helpful, but the configuration would fail much earlier.

Terraform destroy should accept reassigned IP addresses that 403

If a project's resources are deleted outside of Terraform, some of the resources that Terraform is tracking may 403.

IP Addresses, for example:

Error: Error deleting IP reservation block 4f1a2253-2ed6-46ab-a145-bebe327914b5: DELETE https://api.equinix.com/metal/v1/ips/4f1a2253-2ed6-46ab-a145-bebe327914b5: 403 You are not authorized to delete this ip address

terraform destroy should not error in this case. This should be treated as a successful deletion per #44

404 should not error when deleting IP reservations

Deleting an IP reservation that was removed should not be an error:

Error: Error deleting IP reservation block 079e8000-da9f-417c-8953-ffb8facd8f3f: DELETE https://api.equinix.com/metal/v1/ips/079e8000-da9f-417c-8953-ffb8facd8f3f: 404 Not found 

error deleting a metal_vlan resource if the vlan is still associated with a connection

When I try to delete a metal_vlan resource and it is still associated with a connection it returns below panic error instead of a handled error message. The error is fixed after manually removing the association to the connection in the portal, maybe this information should be included in an error message

$ terraform -version
Terraform v0.15.0
on linux_amd64

  • provider registry.terraform.io/equinix/equinix v1.1.0
  • provider registry.terraform.io/equinix/metal v2.0.1

Console output
metal_vlan.vlan: Destroying... [id=3ce69483-8837-4077-84fb-e92d1b119514]

│ Error: Plugin did not respond

│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.

Stack trace from the terraform-provider-metal_v2.0.1 plugin:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xccca40]

goroutine 25 [running]:
github.com/equinix/terraform-provider-metal/metal.ignoreResponseErrors.func1(0x0, 0xfef720, 0xc0004ed2f0, 0xc0006a0c60, 0xfef720)
github.com/equinix/terraform-provider-metal/metal/errors.go:144 +0x60
github.com/equinix/terraform-provider-metal/metal.resourceMetalVlanDelete(0xc000221500, 0xdcd380, 0xc0003e0500, 0x24, 0x150e860)
github.com/equinix/terraform-provider-metal/metal/resource_metal_vlan.go:129 +0x12c
github.com/hashicorp/terraform-plugin-sdk/helper/schema.(*Resource).Apply(0xc000426180, 0xc00020bc20, 0xc000667d40, 0xdcd380, 0xc0003e0500, 0x40e001, 0x20, 0xe3e580)
github.com/hashicorp/[email protected]/helper/schema/resource.go:278 +0x4a6
github.com/hashicorp/terraform-plugin-sdk/helper/schema.(*Provider).Apply(0xc000426300, 0xc0002d98e8, 0xc00020bc20, 0xc000667d40, 0x150e860, 0x0, 0x0)
github.com/hashicorp/[email protected]/helper/schema/provider.go:289 +0x99
github.com/hashicorp/terraform-plugin-sdk/internal/helper/plugin.(*GRPCProviderServer).ApplyResourceChange(0xc00000eb28, 0x10012d0, 0xc00021dd40, 0xc00020f2c0, 0xc00000eb28, 0xc00021dd40, 0xc000754a50)
github.com/hashicorp/[email protected]/internal/helper/plugin/grpc_provider.go:885 +0x88b
github.com/hashicorp/terraform-plugin-sdk/internal/tfplugin5._Provider_ApplyResourceChange_Handler(0xe691c0, 0xc00000eb28, 0x10012d0, 0xc00021dd40, 0xc00020f260, 0x0, 0x10012d0, 0xc00021dd40, 0xc0000bc620, 0xd6)
github.com/hashicorp/[email protected]/internal/tfplugin5/tfplugin5.pb.go:3189 +0x214
google.golang.org/grpc.(*Server).processUnaryRPC(0xc0000be000, 0x10092f8, 0xc00073c900, 0xc000424d00, 0xc00041cf30, 0x14cfd60, 0x0, 0x0, 0x0)
google.golang.org/[email protected]/server.go:995 +0x482
google.golang.org/grpc.(*Server).handleStream(0xc0000be000, 0x10092f8, 0xc00073c900, 0xc000424d00, 0x0)
google.golang.org/[email protected]/server.go:1275 +0xd2c
google.golang.org/grpc.(*Server).serveStreams.func1.1(0xc000366220, 0xc0000be000, 0x10092f8, 0xc00073c900, 0xc000424d00)
google.golang.org/[email protected]/server.go:710 +0xab
created by google.golang.org/grpc.(*Server).serveStreams.func1
google.golang.org/[email protected]/server.go:708 +0xa5

Error: The terraform-provider-metal_v2.0.1 plugin crashed!

This is always indicative of a bug within the plugin. It would be immensely
helpful if you could report the crash with the plugin's maintainers so that it
can be fixed. The output above should help diagnose the issue.

tests and sweeper for metal_volume failing

2021/05/07 13:32:46 [ERR] error running (metal_device): Error listing volumes to sweep: GET https://api.equinix.com/metal/v1/projects/06abbf33-b04c-4995-b8aa-b159b4a4ff33/storage: 404 Datera Storage is EOL, please see https://metal.equinix.com/developers/docs/resilience-recovery/elastic-block-storage/ for more information

Existing users can continue to use the service until the EOL date (in June), but the Terraform testing account does not fit this criteria so the sweeper should be updated to handle a 404 when listing the volumes.

Migrating from the Packet Provider

Continued from packethost/terraform-provider-packet#288

Users coming from the Packet provider can convert their existing configurations to work with this provider.
This Equinix Metal provider is derived from v3.2.0 of the Packet provider.

The packet_ resources have all been renamed to metal_. Instructions to adapt existing projects to this provider should be included in the README.md.

Here are some initial thoughts on what this content should include.


When converting a project from Packet to Equinix Metal:

  • Update to terraform-provider-packet v3.2.0 (Perhaps v3.2.1 to avoid the hardware_reservation_id problem)
  • terraform plan, resolve any diffs before proceeding
  • backup the existing configuration directory and state
  • rename the packet_ references in the config and modules to metal_
  • rename any packethost/packet references in the module to equinix/equinix-metal
  • rename packethost references in the module to equinix
  • repeat these renames within the tfstate files
  • terraform init --upgrade to fetch the equinix-metal provider
  • terraform plan and look for no changes, if the plan is clean it should be safe to apply

It may also be advisable to update to the latest version of Terraform before making any of these changes. A proper versions.tf (the contents of that file, from terraform 0.12-upgrade, required in TF 0.13) and .terraform.lock.hcl file is needed in TF 0.12+ and TF 0.14+ respectively.

Support for Metros

This issue is a planning/placeholder for incoming work related to backend work in progress:

https://feedback.equinixmetal.com/platform/p/introduce-locations-concept-including-support-for-metros

As information becomes available this description will be updated and comments will be added to support the implementation changes.

Depends on equinixmetal-archive/packngo#238

We wil need a new datasource:

  • datasource metal_metro #58

We will also need new metro properties. Generally, these will be optional and adjacent to facility. Facility will become optional, when metro is specified. The metro property will be a slug. Users can fetch additional metro details through a lookup on the metal_metro datasource.

The following need a read-only metro property:

  • datasource metal_spot_market_request (Update: request_id is the only parameter, and device_ids the only attribute)
  • datasource metal_spot_market_price metro parameter (make facility optional) #64
  • datasource metal_ip_block_ranges metro filter #58
  • datasource metal_precreated_ip_block metro property #58
  • datasource metal_volume metro property (Update: volumes can not be metro scoped)
  • datasource metal_facility metro property #31 #58

The following need an optional metro property as an alternative to the facility. One is required, the values should not conflict, but if they do the API response will handle that - we will not try to prevalidate.

  • resource metal_device metro property #46
  • resource metal_spot_market_request #63
  • resource metal_vlan #53
  • resource reserved_ip_block #56

Examples should be broadly be updated to demonstrate metros. A few smaller examples can demonstrate Facilities.

  • Examples are updated to use Metros #65
  • #36 Examples are updated to use Metro supported plans and images #65

Layer2-only readiness

In the future, it may be possible for Equinix Metal devices to provision in Layer2 only configurations. Equinix Metal devices are not all 'servers', some may be appliances provisioned from hardware reservations, some may be 'servers' configured with special operating systems for niche purposes.

What would break in the Terraform provider if a device were created that did not return Layer3 addresses?

Let's suppose that the API would return errors if this device attempted to convert to layer-3 or assign IP addresses.

Let's also suppose that the API could return an initial set of VLAN attachments for this class of devices.

The initial network type would not be 'layer3'. It would likely be some combination of 'layer2-bonded' or 'layer2-individual'. I don't know what to expect with 4 port devices, so let's think broadly about the implications of these behavioral changes.

The API may require the ip_addresses field to be explicitly indicated as [], which would be an error condition today (managed addresses are required).

Or, the API may change the default behavior ip_addresses: null to suit the hardware reservation or operating system selected.

It may be possible to detect that the OS choice will change these behaviors, through features returned with the OS list, or the hardware_reservation list. Would the TF provider need this kind of insight to make decisions to support these changes?

First attached VLAN may be set to Native when native field is not enabled

The first VLAN attachment on an Artista attached devices will have the native vlan feature enabled. In other environments, native vlan must be explicitly enabled.

The Terraform provider must work around this behavior of the API and explicitly disable native mode when the native field is set to false. Since the default value for native is false, this means that even when the native field is omitted, on creation or update, the provider should disable VLAN native mode.

Terraform Version

Provider versions <= 2.0.1

Affected Resource(s)

Please list the resources as a list, for example:

  • metal_port_vlan_attachment

Terraform Configuration Files

resource "metal_device" "test" {
  hostname         = "test"
  plan             = "c2.small.x86"
  facilities       = ["sjc1"]
  operating_system = "ubuntu_20_04"
  billing_cycle    = "hourly"
  project_id       = local.project_id
}

resource "metal_device_network_type" "test" {
  device_id = metal_device.test.id
  type      = "layer2-individual" # Also affects layer2-bonded
}

resource "metal_vlan" "test2" {
  description = "VLAN in New Jersey"
  facility    = "sjc1"
  project_id  = local.project_id
}

resource "metal_port_vlan_attachment" "juniper_first_attachment" {
  device_id = metal_device_network_type.test.id
  vlan_vnid = metal_vlan.test1.vxlan
  port_name = "eth1"
  native = false # THIS WILL BE EFFECTIVELY IGNORED
}

Create needs to do what Update is doing:

A 422 is expected when deactivating native when it is not active. (#48)

Debug Output

Please provider a link to a GitHub Gist containing the complete debug output: https://www.terraform.io/docs/internals/debugging.html. Please do NOT paste the debug output in the issue; just paste a link to the Gist. Note: the debug log will contain your API key, please review the log and delete sensitive secrets before submitting.

404s on deleted resources are treated as errors (continued)

Despite #32 (#43 and #43), 404s on IP reservation deletes (presumably other resources) are not treated as successful deletes.

metal_reserved_ip_block.esx_ip_blocks[0]: Destroying... [id=52980c7c-0db9-47a8-8f5b-0d70aa912ac3]
metal_reserved_ip_block.esx_ip_blocks[1]: Destroying... [id=cc9c5543-0391-4738-8e6f-1eb3cfa3e7e8]

Error: Error deleting IP reservation block 52980c7c-0db9-47a8-8f5b-0d70aa912ac3: DELETE https://api.equinix.com/metal/v1/ips/52980c7c-0db9-47a8-8f5b-0d70aa912ac3: 404 Not found

Error: Error deleting IP reservation block cc9c5543-0391-4738-8e6f-1eb3cfa3e7e8: DELETE https://api.equinix.com/metal/v1/ips/cc9c5543-0391-4738-8e6f-1eb3cfa3e7e8: 404 Not found
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0: =======[RESPONSE]============
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0: HTTP/1.1 404 Not Found
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0: Connection: close
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0: Content-Length: 24
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0: Cache-Control: no-cache
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0: Content-Type: application/json; charset=utf-8
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0: Date: Fri, 26 Mar 2021 19:42:51 GMT
nsport-Security: max-age=15724800; includeSubDomains
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0:
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0: {"errors":["Not found"]}
2021-03-26T15:42:51.275-0400 [DEBUG] plugin.terraform-provider-metal_v1.1.0:
2021/03/26 15:42:51 [DEBUG] metal_reserved_ip_block.esx_ip_blocks[0]: apply errored, but we're indicating that via the Error pointer rather than returning it: Error deleting IP reservation block 52980c7c-0db9-47a8-8f5b-0d70aa912ac3: DELETE https://api.equinix.com/metal/v1/ips/52980c7c-0db9-47a8-8f5b-0d70aa912ac3: 404 Not found

The workaround is to terraform refresh.

post_processing is a new and unsupported device provisioning states

During device provisioning, the API may return a state of post_provisioning.

This is only returned when deploying new, unreleased, images.

Upon encountering this new state, terraform will error with:


│ Error: unexpected state 'post_provisioning', wanted target 'active, failed'. last error: %!s(<nil>)

│   with metal_device.vcf,
│   on main.tf line 8, in resource "metal_device" "vcf":
│    8: resource "metal_device" "vcf" {

This state should be handled if encountered.

state, err := waitForDeviceAttribute(d, []string{"active", "failed"}, []string{"queued", "provisioning"}, "state", meta)

Example config:

provider "metal" {
 auth_token = var.token
}

variable "token" {}
variable "project_id" {}

resource "metal_device" "vcf" {
  hostname = "vcf-esx-01"
  hostname = "tf-test-vcf-marques"
  project_id = var.project_id
  facilities = ["ch3"]
  plan = "m3.large.x86"
  operating_system = "vmware_esxi_7_0_vcf"
  billing_cycle = "hourly"
}
terraform {
  required_providers {
    metal = {
      source = "equinix/metal"
    }
  }
  required_version = ">= 0.13"
}

Add a Data Source for VLANs

It would be helpful to have data source for VLANs after they get created. Currently the Terraform provider only has a VXLAN attribute for the VLAN resource.

Determine if TF acceptance tests are racing and sweeping each other

More interesting errors that seem unrelated. I wonder if the two versions of TF acceptance tests are running side-by-side and the sweeper from one test is knocking out the test resources of the other test. Most of these errors could be explained by a resource being deleted by an external actor.

If sweeping is the problem:

  • and tests across PRs are racing, can we prevent that?
  • and tests in the same PR are racing, can we prevent that?

Tests failures that may be evidence of sweeping:

--- FAIL: TestAccMetalDataSourceProject_Basic (2.42s)
    testing.go:569: Step 0 error: errors during apply:
        
        Error: Not found
        
          on /tmp/tf-test475229150/main.tf line 6:
          (source code not available)
--- FAIL: TestAccMetalProject_BGPBasic (0.77s)
    testing.go:569: Step 0 error: errors during apply:
        
        Error: Not found
        
          on /tmp/tf-test218057823/main.tf line 2:
          (source code not available)
--- FAIL: TestAccMetalProject_BGPUpdate (1.39s)
    testing.go:569: Step 1 error: errors during apply:
        
        Error: Not found
        
          on /tmp/tf-test871845553/main.tf line 2:
          (source code not available)
--- FAIL: TestAccMetalPortVlanAttachment_L2Individual (1017.40s)
    testing.go:569: Step 1 error: errors during apply:
        
        Error: POST https://api.equinix.com/metal/v1/ports/4779f6fa-e488-47fb-9ca1-b5c683224e1b/convert/layer-2: 403 You are not authorized to view this resource 
        
          on /tmp/tf-test315818338/main.tf line 29:
          (source code not available)

Originally posted by @displague in #21 (comment)

hybrid network device unbonded via terraform.

I trying to create metal_device with hybrid-bonded network including 2 vlans

//metal device test
resource "metal_device" "test" {
  hostname         = "test"
  plan             = "c3.small.x86"
  metro            = "fr"
  operating_system = "ubuntu_20_04"
  billing_cycle    = "hourly"
  project_id       = metal_project.project.id
}

resource "metal_device_network_type" "test" {
  device_id = metal_device.test.id
  type      = "hybrid"
}

resource "metal_port_vlan_attachment" "test_vlan3001" {
  device_id = metal_device_network_type.test.id
  port_name = "bond0"
  vlan_vnid = metal_vlan.vlan_frankfurt1.vxlan
}

resource "metal_port_vlan_attachment" "test_vlan3002" {
  device_id = metal_device_network_type.test.id
  port_name = "bond0"
  vlan_vnid = metal_vlan.vlan_frankfurt2.vxlan
}

### Expected Behavior
Terraform should create metal device with layer 3 and then convert network type to Hybrid-bonded with 2 vlans.

### Actual Behavior
Terraform created metal device and set hybrid-unbonded network type with 2 vlans.

When I try to do the same via UI - it works as expected.

Delete operations should treat 404 as success

While destroying resources, I received several 404 responses because I manually deleted the resources outside of Terraform.

404 responses on delete requests should be treated as successful deletions.

Guide: Migrating Facility machines to metros

Users may want to update their existing facility based device deployments to use metro fields instead of facility fields.

Document the process as a guide, wether that involves simply changing the facility/metro fields and running terraform apply, or wether it involves terraform plan; terraform detaint; terraform import; terraform apply or some other combination.

What are the risks that should be avoided?

Draft an initial release

Continued from packethost/terraform-provider-packet#288

This project needs an initial release. This requires:

  • v1.0.0 tag. Other semver values should be considered. There is an opportunity to break from the existing semver to avoid confusion with terraform-provider-packet releases.
    • Reset the Changelog. The first release should list all of the supported resources and in this special case should call out the breaking changes from terraform-provider-packet, referring to issue #1 or the documentation produced from that issue.
  • GPG_PRIVATE_KEY and PASSPHRASE GH action values permitted to publish this provider in https://registry.terraform.io/namespaces/equinix

Unassign vlan 422s are not errors

When unassigning a VLAN, a POST 422 "not assigned" message should not be handled as an error. This is equivalent to a DELETE command returning a 404 on other resources.

Error: POST https://api.equinix.com/metal/v1/ports/a213bf05-d63d-457e-9e1d-ed201e9b12f9/unassign: 422 Virtual network 1300 not assigned 

Similarly, a 403 represents a port that is not associated with an active device. This can also be considered a successful unassignment.

Error: POST https://api.equinix.com/metal/v1/ports/a213bf05-d63d-457e-9e1d-ed201e9b12f9/unassign: 403 You are not authorized to view this resource 

Improve Shared Connection usability

Shared metal_connection resources automatically provision Virtual Circuit resources.

To consume these resources you must with a shared connection:

  • create metal_vlan resources (very likely to need these, especially for dynamic projects)
  • create a metal_connection resource
  • apply or import the metal_connection
  • create a metal_virtual_circuit
  • import the automatically created metal_virtual_circuit
  • apply vlan changes to the metal_virtual_circuit

This becomes a manual process because the metal_cirtual_circuit must be imported.

What could improve the experience when working with shared connections?

I propose one of the following, but am open to other approaches:

resource "metal_connection_shared" "shared" {
   # connection params, except type which is always shared. 
   #  options unique to dedicated connections may be removed.
    name            = "My Interconnection"
    organization_id = local.my_organization_id
    project_id      = local.my_project_id
    metro           = "sv"
    redundancy      = "redundant"
    # implied / type            = "shared"

   # virtual-circuit params
    port_id = data.metal_connection.test.ports[0].id
    vlan_id = metal_vlan.test.id
    nni_vlan = 1056
   # inferred  / connection_id = local.conn_id
   # duplicated / project_id = local.project_id
}

Alternatively:

resource "metal_virtual_circuit_attachment" "test" {
    connection_id = local.conn_id
    project_id = local.project_id
   # does not create a new VC, applies settings to the matching virtual connection or errors if it is not matched

    port_id = data.metal_connection.test.ports[0].id
    vlan_id = metal_vlan.test.id
    nni_vlan = 1056
}

Implement Connections resources

What problem are you facing?

Equinix Metal offers Connections through Equinix Fabric. These are not made available through this provider.

How could the Equinix Metal Terraform Provider help solve your problem?

Implement Datasources

  • #41 Connections (by organization or project)
    • #41 Connection Ports
  • #41 Virtual Circuits Datasource
  • Events (We haven't implemented these for other resources. I'm not sure what benefit they provide in Terraform. Listed only for completeness.)
    • Connections (Not planned)
    • Ports (Not planned)
    • Virtual Circuits (Not planned)

Implement Resources

  • Connections Resource #76
    • Connection Ports (computed)
    • Virtual Circuits (computed) (Use independent virtual-circuit datasource or resources)
  • Virtual Circuits Resource #92

Depends on equinixmetal-archive/packngo#228 equinixmetal-archive/packngo#234 (more context there)


Initial Connection shape proposal (see comments for revisions):

resource "metal_connection" "conn" {
  // create only
  type         = "string" // shared | dedicated
  speed        = 0        // int bps, rather than permitted "123 mbps" format
  organization = "string" // GET returns this as {href}
  metro        = "string" // returned as {href}
  facility     = "string" // returned as {href}, create either metro or facility, both will be returned

  // create and update
  name          = "string"
  description   = "string"
  contact_email = "string"
  redundancy    = "string" // primary | redundant
  tags = [
    "string"
  ]

  // read only
  id     = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  status = "string"
  ports {
    primary {
      id        = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      role      = "string"
      status    = "string"
      switch_id = "string"
      // virtual_circuits is promoted to connection level property
    }
    secondary {
      // same as primary, except "role=secondary"
    }
  }

  // set type (multiple, removable, updateable)
  // these are read from "ports" above, included in /connection/{id}/ports/{id}
  // (virtual_circuits list can come from either port, they should have the same list,
  // we can map by id when sync'ing, just-in-case)
  // these are updated or deleted through /virtual-circuits/{id}
  virtual_circuit {
    // create only
    nni_vlan = 0
    project = "" // returned as {href}

    // create and update
    name        = "string"
    description = "string"
    speed       = 0
    tags = [
      "string"
    ]
    vnid = 0

    // read only
    status          = "string"
    id              = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    virtual_network = "" // returned as {href} 
    // hide this if it is redundant to nni_vlan or vnid?
  }
}

metal_reserved_ip_block should be returned when 'created'

A module can't function with a cidr_notation value of /0. Terraform resources are generally expected to return when the resource is ready to use.

The Terraform provider should adopt a behavior of waiting for themetal_reserved_ip_block to have a state of created before releasing the resource. In some cases, a user may be ok with this resource being released early, so a behavior flag could be used to toggle that.

Originally posted by @displague in equinix/terraform-equinix-metal-anthos-on-baremetal#74 (comment)

Update TF Acceptance tests to use TF 1.0.2

I attempted to update the TF version in #154 to 1.0.2. This resulting in the following error:

=== RUN   TestAccDataSourceMetalDevice_Basic
cannot run Terraform provider tests: unexpected error: openpgp: signature made by unknown entity
FAIL	github.com/equinix/terraform-provider-metal/metal	0.140s

Uppercase `metro` attribute causes resource destruction

Hi there,

Terraform Version

Terraform v0.15.5
on linux_amd64

Affected Resource(s)

Please list the resources as a list, for example:

  • metal_device

If this issue appears to affect multiple resources, it may be an issue with Terraform's core, so please mention this.

Terraform Configuration Files

resource "metal_device" "node1" {
  hostname         = "node1"
  plan             = "c3.medium.x86"
  metro            = "FR"
  operating_system = "custom_ipxe"
  ipxe_script_url  = "http://example.com/foo.ipxe"
  always_pxe       = true

  project_id    = local.metal_project_id
  billing_cycle = "hourly"
}

Expected Behavior

On a subsequent apply, the resource shouldn't change.

Actual Behavior

Terraform proposed replacing the metal_device resource entirely (which would have caused a destroy of the server, and creation of the new one.

It seems the metro name (FR) got downcased during the first apply, but while comparing on the next terraform apply, this was considered to be a change requiring replacement:

  # metal_device.node1 must be replaced
-/+ resource "metal_device" "node1" {
      ~ access_private_ipv4              = "10.25.19.131" -> (known after apply)
      ~ access_public_ipv4               = "145.40.93.171" -> (known after apply)
      ~ access_public_ipv6               = "2604:xxxx:xxxx:xxxx::3" -> (known after apply)
      ~ created                          = "2021-06-05T10:00:15Z" -> (known after apply)
      ~ deployed_facility                = "fr2" -> (known after apply)
      + deployed_hardware_reservation_id = (known after apply)
      - facilities                       = [
          - "fr2",
        ] -> null
      ~ id                               = "c554b60b-9ca6-xxxx-xxxx-8137f8d0eff6" -> (known after apply)
      ~ ipxe_script_url                  = "http://example.com/foo.ipxe" -> "http://example.com/foo.ipxe"
      ~ locked                           = false -> (known after apply)
      ~ metro                            = "fr" -> "FR" # forces replacement
      ~ network                          = [
          - {

Changing the metro to be downcased in the .hcl helped to workaround - but it's very confusing.

In your docs, metro codes are shown in uppercase most of the time. If the terraform provider accepts both downcased and upcased variants, a subsequent apply should be a no-op.

Steps to Reproduce

Please list the steps required to reproduce the issue, for example:

  1. terraform apply

test TestAccMetalSSHKey_projectImportBasic failures

From SSH Key projectImportBasic:

--- FAIL: TestAccMetalSSHKey_projectImportBasic (2.27s)
    testing.go:569: Step 1 error: ImportStateVerify attributes not equivalent. Difference is shown below. Top is actual, bottom is expected.
        
        (map[string]string) {
        }
        
        
        (map[string]string) (len=1) {
         (string) (len=10) "project_id": (string) (len=36) "96e8fa35-58df-487b-be70-63d05f7a9ea7"
        }
        
=== RUN   TestAccMetalSSHKey_importBasic

Originally posted by @t0mk in #21 (comment)

Implement type = hybrid-bonded for metal_device_network_type

Depends on equinixmetal-archive/packngo#231

With the upcoming https://feedback.equinixmetal.com/networking-features/p/mixed-mode-layer-23-for-hybrid-cloud feature, we'll need device support for network-type = "hybrid-bonded".

This is exciting because it means that in Terraform, we should not require the use of the metal_device_network_type resource to toggle resource modes for the most common uses.

One possible complication is that devices with metal_device_network_type resources defined as layer3 could be automatically transitioned to hybrid-bonded if a vlan is attached. Terraform would want to restore the layer3 value, which would entail detaching all existing vlans first.

Another complication is that a configuration like the following would succeed, but would have plan jitter because the network_type would be hybrid-bonded on subsequent reads.

resource "metal_device_network_type" "test" {
  device_id = metal_device.test.id
  type      = "layer3"
}

resource "metal_port_vlan_attachment" "test" {
  device_id = metal_device_network_type.test.id
  port_name = "eth1"
  vlan_vnid = metal_vlan.test.vxlan
}

Users would want to set type = "hybrid-bonded" in this case.

Notes

  • When a server is provisioned, the initial state for the first bond is L3 Bonded. Other bond ports (if present) are initialized in L2 Bonded mode. (The only exception are x1.small.x86 / t1.small.x86 servers, as they only support Hybrid unbonded mode)
  • Ports can not transition between some modes: ("any" means bonded and unbonded, list shows from -> to)
    • L3 -> L2 unbonded (also called "individual")
    • L2 unbonded -> L3
    • L2 (any) -> Hybrid (any)
    • Hybrid (any) -> L2 (any)
    • Hybrid (any) -> Hybrid (alternate)
  • L3 is always bonded

Affected Resource(s)

Please list the resources as a list, for example:

  • metal_device_network_type

Create a metal_port datasource

Introducing metal_port as a datasource, ahead of any refactoring to offer a metal_port resource (#12 (comment)) will give users the ability to work with ports that may be in use by appliances, connections, or devices. The attributes of this datasource will give us a head start on a metal_port resource.

This data source could offer device_id search fields in addition to id (port_id). Port name may also be a helpful search field.

For users looking to fetch the metal_device_network_type of a device, this would be possible by fetch the network type on each port and performing the same logic used by metal_device_network_type (this logic is not present in the EM API, this TF provider formulates it, like the EM Portal. This single device "network_type" does not fit the broad reality of port configurations across all EM device models.

Users can get to the device_id through the existing metal_vlan data source. Likewise, ports can be listed on the metal_device datasource. However, there is no TF way (that I know of now) to get the ports related to a VLAN (or vice-versa) today.

This resource should follow /ports/{id}. There may be other port attributes exposed in devices, connections, VLAN, or other resources, but my first inclination is to avoid including those in metal_ports. If we've omitted useful fields in those other resources, that are within a ports attribute, we should fill in the missing attributes in those resources.

Crash during delete

I attempted a terraform destroy and received the following crash. On a subsequent terraform destroy there was no error.

It looks like metal.ignoreResponseErrors may not be handling a null value correctly.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

metal_vlan.private_vlans[1]: Destroying... [id=efffcb9b-b338-42ad-a0f5-15bff1e35f42]
metal_vlan.private_vlans[0]: Destroying... [id=d97e954a-a815-4b55-b27e-a1e74e102b44]
metal_device_network_type.esxi_hosts[0]: Destroying... [id=1170631c-4959-4a83-b792-a8a59f449826]
metal_vlan.private_vlans[2]: Destroying... [id=80bcb037-be64-4630-bfd7-0220d2e7b18d]
metal_vlan.public_vlans[0]: Destroying... [id=a0043d83-2b7e-41cd-907b-f417ed663416]
metal_device_network_type.esxi_hosts[1]: Destroying... [id=7d41174f-abbb-4e2a-a5f5-94730bd83750]
metal_device_network_type.esxi_hosts[1]: Destruction complete after 0s
metal_device_network_type.esxi_hosts[0]: Destruction complete after 0s
metal_device.esxi_hosts[0]: Destroying... [id=1170631c-4959-4a83-b792-a8a59f449826]
metal_device.esxi_hosts[1]: Destroying... [id=7d41174f-abbb-4e2a-a5f5-94730bd83750]
╷
│ Error: Plugin did not respond
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵
╷
│ Error: Plugin did not respond
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵
╷
│ Error: Plugin did not respond
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵
╷
│ Error: Plugin did not respond
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵
╷
│ Error: Plugin did not respond
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵
╷
│ Error: Plugin did not respond
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵

Stack trace from the terraform-provider-metal_v2.0.1 plugin:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x18cb400]

goroutine 29 [running]:
github.com/equinix/terraform-provider-metal/metal.ignoreResponseErrors.func1(0x0, 0x1bef1a0, 0xc0001d7fb0, 0xc0008541c0, 0x1bef1a0)
	github.com/equinix/terraform-provider-metal/metal/errors.go:144 +0x60
github.com/equinix/terraform-provider-metal/metal.resourceMetalVlanDelete(0xc00017e5b0, 0x19cc7c0, 0xc0005a8500, 0x24, 0x21123a0)
	github.com/equinix/terraform-provider-metal/metal/resource_metal_vlan.go:129 +0x12c
github.com/hashicorp/terraform-plugin-sdk/helper/schema.(*Resource).Apply(0xc00058d700, 0xc0003ac2d0, 0xc0003aa180, 0x19cc7c0, 0xc0005a8500, 0x100df01, 0x20, 0x1a3d5a0)
	github.com/hashicorp/[email protected]/helper/schema/resource.go:278 +0x4a6
github.com/hashicorp/terraform-plugin-sdk/helper/schema.(*Provider).Apply(0xc00058d880, 0xc0006378e8, 0xc0003ac2d0, 0xc0003aa180, 0x21123a0, 0x0, 0x0)
	github.com/hashicorp/[email protected]/helper/schema/provider.go:289 +0x99
github.com/hashicorp/terraform-plugin-sdk/internal/helper/plugin.(*GRPCProviderServer).ApplyResourceChange(0xc0005860f0, 0x1c00e90, 0xc000392720, 0xc000758120, 0xc0005860f0, 0xc000392720, 0xc0003bba50)
	github.com/hashicorp/[email protected]/internal/helper/plugin/grpc_provider.go:885 +0x88b
github.com/hashicorp/terraform-plugin-sdk/internal/tfplugin5._Provider_ApplyResourceChange_Handler(0x1a68a40, 0xc0005860f0, 0x1c00e90, 0xc000392720, 0xc000758060, 0x0, 0x1c00e90, 0xc000392720, 0xc0003bc000, 0xb1)
	github.com/hashicorp/[email protected]/internal/tfplugin5/tfplugin5.pb.go:3189 +0x214
google.golang.org/grpc.(*Server).processUnaryRPC(0xc000166160, 0x1c09078, 0xc0005ef380, 0xc0005ea600, 0xc000117680, 0x20d3e80, 0x0, 0x0, 0x0)
	google.golang.org/[email protected]/server.go:995 +0x482
google.golang.org/grpc.(*Server).handleStream(0xc000166160, 0x1c09078, 0xc0005ef380, 0xc0005ea600, 0x0)
	google.golang.org/[email protected]/server.go:1275 +0xd2c
google.golang.org/grpc.(*Server).serveStreams.func1.1(0xc00058a190, 0xc000166160, 0x1c09078, 0xc0005ef380, 0xc0005ea600)
	google.golang.org/[email protected]/server.go:710 +0xab
created by google.golang.org/grpc.(*Server).serveStreams.func1
	google.golang.org/[email protected]/server.go:708 +0xa5

Error: The terraform-provider-metal_v2.0.1 plugin crashed!

This is always indicative of a bug within the plugin. It would be immensely
helpful if you could report the crash with the plugin's maintainers so that it
can be fixed. The output above should help diagnose the issue.

Introduce METAL_AUTH_TOKEN environment variable

Introduce auth_token environment variable METAL_AUTH_TOKEN with higher priority than PACKET_AUTH_TOKEN

https://github.com/equinix/terraform-provider-metal/pull/21/files#diff-f83e6f29b5ad609210e057442d576d3c8ff966ea294706f37c89d102fd3059f1R20

There should also be documentation updates related to this change.

We should also deprecate the PACKET_AUTH_TOKEN. It should be trivial to continue to support the legacy environment variable for some period of time.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.