From 95e95bd9d1d488bc8135beebd370f381e1c23cea Mon Sep 17 00:00:00 2001 From: Erik Zilber Date: Mon, 2 Dec 2024 12:57:51 -0500 Subject: [PATCH] Added support for missing User-related fields (#622) * Added support for missing user fields * Reran GetMonthlyTransfer fixture --- account_user_grants.go | 43 +- account_users.go | 2 + test/integration/account_user_grants_test.go | 26 +- .../TestInstance_GetMonthlyTransfer.yaml | 443 ++++++++---------- .../fixtures/TestUserGrants_Update.yaml | 76 +-- .../TestUserGrants_UpdateNoAccess.yaml | 76 +-- test/unit/account_user_grants_test.go | 144 ++++++ test/unit/account_users_test.go | 126 +++++ .../fixtures/account_user_grants_get.json | 96 ++++ .../fixtures/account_user_grants_update.json | 96 ++++ test/unit/fixtures/account_users_create.json | 16 + test/unit/fixtures/account_users_get.json | 17 + test/unit/fixtures/account_users_list.json | 24 + test/unit/fixtures/account_users_update.json | 17 + 14 files changed, 822 insertions(+), 380 deletions(-) create mode 100644 test/unit/account_user_grants_test.go create mode 100644 test/unit/account_users_test.go create mode 100644 test/unit/fixtures/account_user_grants_get.json create mode 100644 test/unit/fixtures/account_user_grants_update.json create mode 100644 test/unit/fixtures/account_users_create.json create mode 100644 test/unit/fixtures/account_users_get.json create mode 100644 test/unit/fixtures/account_users_list.json create mode 100644 test/unit/fixtures/account_users_update.json diff --git a/account_user_grants.go b/account_user_grants.go index f0ca1dc7b..8b6227e9e 100644 --- a/account_user_grants.go +++ b/account_user_grants.go @@ -20,9 +20,12 @@ type GlobalUserGrants struct { AddLinodes bool `json:"add_linodes"` AddLongview bool `json:"add_longview"` AddNodeBalancers bool `json:"add_nodebalancers"` + AddPlacementGroups bool `json:"add_placement_groups"` AddStackScripts bool `json:"add_stackscripts"` AddVolumes bool `json:"add_volumes"` + AddVPCs bool `json:"add_vpcs"` CancelAccount bool `json:"cancel_account"` + ChildAccountAccess bool `json:"child_account_access"` LongviewSubscription bool `json:"longview_subscription"` } @@ -38,29 +41,33 @@ type GrantedEntity struct { } type UserGrants struct { - Database []GrantedEntity `json:"database"` - Domain []GrantedEntity `json:"domain"` - Firewall []GrantedEntity `json:"firewall"` - Image []GrantedEntity `json:"image"` - Linode []GrantedEntity `json:"linode"` - Longview []GrantedEntity `json:"longview"` - NodeBalancer []GrantedEntity `json:"nodebalancer"` - StackScript []GrantedEntity `json:"stackscript"` - Volume []GrantedEntity `json:"volume"` + Database []GrantedEntity `json:"database"` + Domain []GrantedEntity `json:"domain"` + Firewall []GrantedEntity `json:"firewall"` + Image []GrantedEntity `json:"image"` + Linode []GrantedEntity `json:"linode"` + Longview []GrantedEntity `json:"longview"` + NodeBalancer []GrantedEntity `json:"nodebalancer"` + PlacementGroup []GrantedEntity `json:"placement_group"` + StackScript []GrantedEntity `json:"stackscript"` + Volume []GrantedEntity `json:"volume"` + VPC []GrantedEntity `json:"vpc"` Global GlobalUserGrants `json:"global"` } type UserGrantsUpdateOptions struct { - Database []GrantedEntity `json:"database,omitempty"` - Domain []EntityUserGrant `json:"domain,omitempty"` - Firewall []EntityUserGrant `json:"firewall,omitempty"` - Image []EntityUserGrant `json:"image,omitempty"` - Linode []EntityUserGrant `json:"linode,omitempty"` - Longview []EntityUserGrant `json:"longview,omitempty"` - NodeBalancer []EntityUserGrant `json:"nodebalancer,omitempty"` - StackScript []EntityUserGrant `json:"stackscript,omitempty"` - Volume []EntityUserGrant `json:"volume,omitempty"` + Database []GrantedEntity `json:"database,omitempty"` + Domain []EntityUserGrant `json:"domain,omitempty"` + Firewall []EntityUserGrant `json:"firewall,omitempty"` + Image []EntityUserGrant `json:"image,omitempty"` + Linode []EntityUserGrant `json:"linode,omitempty"` + Longview []EntityUserGrant `json:"longview,omitempty"` + NodeBalancer []EntityUserGrant `json:"nodebalancer,omitempty"` + PlacementGroup []EntityUserGrant `json:"placement_group,omitempty"` + StackScript []EntityUserGrant `json:"stackscript,omitempty"` + Volume []EntityUserGrant `json:"volume,omitempty"` + VPC []EntityUserGrant `json:"vpc,omitempty"` Global GlobalUserGrants `json:"global"` } diff --git a/account_users.go b/account_users.go index 88615fa81..54dc10bce 100644 --- a/account_users.go +++ b/account_users.go @@ -47,6 +47,7 @@ type UserCreateOptions struct { type UserUpdateOptions struct { Username string `json:"username,omitempty"` Restricted *bool `json:"restricted,omitempty"` + Email string `json:"email,omitempty"` } // UnmarshalJSON implements the json.Unmarshaler interface @@ -102,6 +103,7 @@ func (i User) GetCreateOptions() (o UserCreateOptions) { func (i User) GetUpdateOptions() (o UserUpdateOptions) { o.Username = i.Username o.Restricted = copyBool(&i.Restricted) + o.Email = i.Email return } diff --git a/test/integration/account_user_grants_test.go b/test/integration/account_user_grants_test.go index 4f09d3d00..45cdd0dae 100644 --- a/test/integration/account_user_grants_test.go +++ b/test/integration/account_user_grants_test.go @@ -23,17 +23,19 @@ func TestUserGrants_Update(t *testing.T) { accessLevel := linodego.AccessLevelReadOnly globalGrants := linodego.GlobalUserGrants{ - AccountAccess: &accessLevel, - AddDomains: false, - AddDatabases: true, - AddFirewalls: true, - AddImages: true, - AddLinodes: false, - AddLongview: true, - AddNodeBalancers: false, - AddStackScripts: true, - AddVolumes: true, - CancelAccount: false, + AccountAccess: &accessLevel, + AddDomains: false, + AddDatabases: true, + AddFirewalls: true, + AddImages: true, + AddLinodes: false, + AddLongview: true, + AddNodeBalancers: false, + AddPlacementGroups: false, + AddStackScripts: true, + AddVolumes: true, + AddVPCs: true, + CancelAccount: false, } grants, err := client.UpdateUserGrants(context.TODO(), username, linodego.UserGrantsUpdateOptions{ @@ -83,8 +85,10 @@ func TestUserGrants_UpdateNoAccess(t *testing.T) { grants.Linode, grants.Longview, grants.NodeBalancer, + grants.PlacementGroup, grants.StackScript, grants.Volume, + grants.VPC, } for _, grantField := range grantFields { diff --git a/test/integration/fixtures/TestInstance_GetMonthlyTransfer.yaml b/test/integration/fixtures/TestInstance_GetMonthlyTransfer.yaml index c0c208112..d252d03e7 100644 --- a/test/integration/fixtures/TestInstance_GetMonthlyTransfer.yaml +++ b/test/integration/fixtures/TestInstance_GetMonthlyTransfer.yaml @@ -15,276 +15,237 @@ interactions: method: GET response: body: '{"data": [{"id": "ap-west", "label": "Mumbai, IN", "country": "in", "capabilities": - ["Linodes", "Backups", "NodeBalancers", "Block Storage", "GPU Linodes", "Kubernetes", - "Cloud Firewall", "Vlans", "Block Storage Migrations", "Managed Databases", - "Metadata", "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.105.34.5, - 172.105.35.5, 172.105.36.5, 172.105.37.5, 172.105.38.5, 172.105.39.5, 172.105.40.5, - 172.105.41.5, 172.105.42.5, 172.105.43.5", "ipv6": "1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678"}, + ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", "Block Storage", + "GPU Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "172.105.34.5,172.105.35.5,172.105.36.5,172.105.37.5,172.105.38.5,172.105.39.5,172.105.40.5,172.105.41.5,172.105.42.5,172.105.43.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "ca-central", "label": "Toronto, CA", "country": - "ca", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", "Managed - Databases", "Metadata", "Placement Group"], "status": "ok", "resolvers": {"ipv4": - "172.105.0.5, 172.105.3.5, 172.105.4.5, 172.105.5.5, 172.105.6.5, 172.105.7.5, - 172.105.8.5, 172.105.9.5, 172.105.10.5, 172.105.11.5", "ipv6": "1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678"}, + "ca", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "172.105.0.5,172.105.3.5,172.105.4.5,172.105.5.5,172.105.6.5,172.105.7.5,172.105.8.5,172.105.9.5,172.105.10.5,172.105.11.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "ap-southeast", "label": "Sydney, AU", "country": - "au", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", "Managed - Databases", "Metadata", "Placement Group"], "status": "ok", "resolvers": {"ipv4": - "172.105.166.5, 172.105.169.5, 172.105.168.5, 172.105.172.5, 172.105.162.5, - 172.105.170.5, 172.105.167.5, 172.105.171.5, 172.105.181.5, 172.105.161.5", - "ipv6": "1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": - null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-iad", "label": - "Washington, DC", "country": "us", "capabilities": ["Linodes", "Block Storage - Encryption", "Backups", "NodeBalancers", "Block Storage", "Object Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", - "Premium Plans", "Placement Group"], "status": "ok", "resolvers": {"ipv4": "139.144.192.62, - 139.144.192.60, 139.144.192.61, 139.144.192.53, 139.144.192.54, 139.144.192.67, - 139.144.192.69, 139.144.192.66, 139.144.192.52, 139.144.192.68", "ipv6": "1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678"}, + "au", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "172.105.166.5,172.105.169.5,172.105.168.5,172.105.172.5,172.105.162.5,172.105.170.5,172.105.167.5,172.105.171.5,172.105.181.5,172.105.161.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-iad", "label": "Washington, DC", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": + "139.144.192.62,139.144.192.60,139.144.192.61,139.144.192.53,139.144.192.54,139.144.192.67,139.144.192.69,139.144.192.66,139.144.192.52,139.144.192.68", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-ord", "label": "Chicago, IL", "country": - "us", "capabilities": ["Linodes", "Block Storage Encryption", "Backups", "NodeBalancers", - "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", - "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium Plans", "Placement - Group"], "status": "ok", "resolvers": {"ipv4": "172.232.0.17, 172.232.0.16, - 172.232.0.21, 172.232.0.13, 172.232.0.22, 172.232.0.9, 172.232.0.19, 172.232.0.20, - 172.232.0.15, 172.232.0.18", "ipv6": "1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678"}, "placement_group_limits": - {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": - "core"}, {"id": "fr-par", "label": "Paris, FR", "country": "fr", "capabilities": - ["Linodes", "Block Storage Encryption", "Backups", "NodeBalancers", "Block Storage", - "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", - "Managed Databases", "Metadata", "Premium Plans", "Placement Group"], "status": - "ok", "resolvers": {"ipv4": "172.232.32.21, 172.232.32.23, 172.232.32.17, 172.232.32.18, - 172.232.32.16, 172.232.32.22, 172.232.32.20, 172.232.32.14, 172.232.32.11, 172.232.32.12", - "ipv6": "1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": - null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-sea", "label": - "Seattle, WA", "country": "us", "capabilities": ["Linodes", "Block Storage Encryption", + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", + "Premium Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": + {"ipv4": "172.232.0.17,172.232.0.16,172.232.0.21,172.232.0.13,172.232.0.22,172.232.0.9,172.232.0.19,172.232.0.20,172.232.0.15,172.232.0.18", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "fr-par", "label": "Paris, FR", "country": + "fr", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", + "Premium Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": + {"ipv4": "172.232.32.21,172.232.32.23,172.232.32.17,172.232.32.18,172.232.32.16,172.232.32.22,172.232.32.20,172.232.32.14,172.232.32.11,172.232.32.12", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-sea", "label": "Seattle, WA", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", - "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.232.160.19, 172.232.160.21, - 172.232.160.17, 172.232.160.15, 172.232.160.18, 172.232.160.8, 172.232.160.12, - 172.232.160.11, 172.232.160.14, 172.232.160.16", "ipv6": "1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678"}, + "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.232.160.19,172.232.160.21,172.232.160.17,172.232.160.15,172.232.160.18,172.232.160.8,172.232.160.12,172.232.160.11,172.232.160.14,172.232.160.16", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "br-gru", "label": "Sao Paulo, BR", "country": - "br", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Object Storage", "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", - "Premium Plans", "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.233.0.4, - 172.233.0.9, 172.233.0.7, 172.233.0.12, 172.233.0.5, 172.233.0.13, 172.233.0.10, - 172.233.0.6, 172.233.0.8, 172.233.0.11", "ipv6": "1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678"}, + "br", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.233.0.4,172.233.0.9,172.233.0.7,172.233.0.12,172.233.0.5,172.233.0.13,172.233.0.10,172.233.0.6,172.233.0.8,172.233.0.11", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "nl-ams", "label": "Amsterdam, NL", "country": - "nl", "capabilities": ["Linodes", "Block Storage Encryption", "Backups", "NodeBalancers", - "Block Storage", "Object Storage", "Kubernetes", "Cloud Firewall", "Vlans", - "VPCs", "Managed Databases", "Metadata", "Premium Plans", "Placement Group"], - "status": "ok", "resolvers": {"ipv4": "172.233.33.36, 172.233.33.38, 172.233.33.35, - 172.233.33.39, 172.233.33.34, 172.233.33.33, 172.233.33.31, 172.233.33.30, 172.233.33.37, - 172.233.33.32", "ipv6": "1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678"}, "placement_group_limits": - {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": - "core"}, {"id": "se-sto", "label": "Stockholm, SE", "country": "se", "capabilities": - ["Linodes", "Block Storage Encryption", "Backups", "NodeBalancers", "Block Storage", - "Object Storage", "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed - Databases", "Metadata", "Premium Plans", "Placement Group"], "status": "ok", - "resolvers": {"ipv4": "172.232.128.24, 172.232.128.26, 172.232.128.20, 172.232.128.22, - 172.232.128.25, 172.232.128.19, 172.232.128.23, 172.232.128.18, 172.232.128.21, - 172.232.128.27", "ipv6": "1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678"}, "placement_group_limits": - {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": - "core"}, {"id": "es-mad", "label": "Madrid, ES", "country": "es", "capabilities": - ["Linodes", "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", - "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group"], - "status": "ok", "resolvers": {"ipv4": "172.233.111.6,172.233.111.17,172.233.111.21,172.233.111.25,172.233.111.19,172.233.111.12,172.233.111.26,172.233.111.16,172.233.111.18,172.233.111.9", + "nl", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": + "172.233.33.36,172.233.33.38,172.233.33.35,172.233.33.39,172.233.33.34,172.233.33.33,172.233.33.31,172.233.33.30,172.233.33.37,172.233.33.32", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "se-sto", "label": "Stockholm, SE", "country": + "se", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": + "172.232.128.24,172.232.128.26,172.232.128.20,172.232.128.22,172.232.128.25,172.232.128.19,172.232.128.23,172.232.128.18,172.232.128.21,172.232.128.27", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "es-mad", "label": "Madrid, ES", "country": + "es", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.233.111.6,172.233.111.17,172.233.111.21,172.233.111.25,172.233.111.19,172.233.111.12,172.233.111.26,172.233.111.16,172.233.111.18,172.233.111.9", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "in-maa", "label": "Chennai, IN", "country": - "in", "capabilities": ["Linodes", "Block Storage Encryption", "Backups", "NodeBalancers", - "Block Storage", "Object Storage", "Kubernetes", "Cloud Firewall", "Vlans", - "VPCs", "Managed Databases", "Metadata", "Premium Plans", "Placement Group"], - "status": "ok", "resolvers": {"ipv4": "172.232.96.17, 172.232.96.26, 172.232.96.19, - 172.232.96.20, 172.232.96.25, 172.232.96.21, 172.232.96.18, 172.232.96.22, 172.232.96.23, - 172.232.96.24", "ipv6": "1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678"}, "placement_group_limits": - {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": - "core"}, {"id": "jp-osa", "label": "Osaka, JP", "country": "jp", "capabilities": - ["Linodes", "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU - Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", - "Metadata", "Premium Plans", "Placement Group"], "status": "ok", "resolvers": - {"ipv4": "172.233.64.44, 172.233.64.43, 172.233.64.37, 172.233.64.40, 172.233.64.46, - 172.233.64.41, 172.233.64.39, 172.233.64.42, 172.233.64.45, 172.233.64.38", - "ipv6": "1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": - null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "it-mil", "label": - "Milan, IT", "country": "it", "capabilities": ["Linodes", "Backups", "NodeBalancers", - "Block Storage", "Object Storage", "Kubernetes", "Cloud Firewall", "Vlans", - "VPCs", "Metadata", "Premium Plans", "Placement Group"], "status": "ok", "resolvers": - {"ipv4": "172.232.192.19, 172.232.192.18, 172.232.192.16, 172.232.192.20, 172.232.192.24, - 172.232.192.21, 172.232.192.22, 172.232.192.17, 172.232.192.15, 172.232.192.23", - "ipv6": "1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": - null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-mia", "label": - "Miami, FL", "country": "us", "capabilities": ["Linodes", "Block Storage Encryption", + "in", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium - Plans", "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.233.160.34, - 172.233.160.27, 172.233.160.30, 172.233.160.29, 172.233.160.32, 172.233.160.28, - 172.233.160.33, 172.233.160.26, 172.233.160.25, 172.233.160.31", "ipv6": "1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678"}, + Plans", "Placement Group", "StackScripts", "NETINT Quadra T1U"], "status": "ok", + "resolvers": {"ipv4": "172.232.96.17,172.232.96.26,172.232.96.19,172.232.96.20,172.232.96.25,172.232.96.21,172.232.96.18,172.232.96.22,172.232.96.23,172.232.96.24", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "jp-osa", "label": "Osaka, JP", "country": + "jp", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", + "Premium Plans", "Placement Group", "StackScripts"], "status": "ok", "resolvers": + {"ipv4": "172.233.64.44,172.233.64.43,172.233.64.37,172.233.64.40,172.233.64.46,172.233.64.41,172.233.64.39,172.233.64.42,172.233.64.45,172.233.64.38", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "it-mil", "label": "Milan, IT", "country": + "it", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.232.192.19,172.232.192.18,172.232.192.16,172.232.192.20,172.232.192.24,172.232.192.21,172.232.192.22,172.232.192.17,172.232.192.15,172.232.192.23", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-mia", "label": "Miami, FL", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium + Plans", "Placement Group", "StackScripts", "NETINT Quadra T1U"], "status": "ok", + "resolvers": {"ipv4": "172.233.160.34,172.233.160.27,172.233.160.30,172.233.160.29,172.233.160.32,172.233.160.28,172.233.160.33,172.233.160.26,172.233.160.25,172.233.160.31", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "id-cgk", "label": "Jakarta, ID", "country": - "id", "capabilities": ["Linodes", "Block Storage Encryption", "Backups", "NodeBalancers", - "Block Storage", "Object Storage", "Kubernetes", "Cloud Firewall", "Vlans", - "VPCs", "Metadata", "Premium Plans", "Placement Group"], "status": "ok", "resolvers": - {"ipv4": "172.232.224.23, 172.232.224.32, 172.232.224.26, 172.232.224.27, 172.232.224.21, - 172.232.224.24, 172.232.224.22, 172.232.224.20, 172.232.224.31, 172.232.224.28", - "ipv6": "1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": - null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-lax", "label": - "Los Angeles, CA", "country": "us", "capabilities": ["Linodes", "Block Storage - Encryption", "Backups", "NodeBalancers", "Block Storage", "Object Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", - "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.233.128.45, 172.233.128.38, - 172.233.128.53, 172.233.128.37, 172.233.128.34, 172.233.128.36, 172.233.128.33, - 172.233.128.39, 172.233.128.43, 172.233.128.44", "ipv6": "1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678"}, + "id", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.232.224.23,172.232.224.32,172.232.224.26,172.232.224.27,172.232.224.21,172.232.224.24,172.232.224.22,172.232.224.20,172.232.224.31,172.232.224.28", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-lax", "label": "Los Angeles, CA", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "Kubernetes", + "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts", "NETINT Quadra T1U"], "status": "ok", "resolvers": {"ipv4": + "172.233.128.45,172.233.128.38,172.233.128.53,172.233.128.37,172.233.128.34,172.233.128.36,172.233.128.33,172.233.128.39,172.233.128.43,172.233.128.44", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "gb-lon", "label": "London 2, UK", "country": - "gb", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", - "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.236.0.46,172.236.0.50,172.236.0.47,172.236.0.53,172.236.0.52,172.236.0.45,172.236.0.49,172.236.0.51,172.236.0.54,172.236.0.48", + "gb", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Kubernetes", "Cloud Firewall", + "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium Plans", "Placement + Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.236.0.46,172.236.0.50,172.236.0.47,172.236.0.53,172.236.0.52,172.236.0.45,172.236.0.49,172.236.0.51,172.236.0.54,172.236.0.48", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "au-mel", "label": "Melbourne, AU", "country": - "au", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", - "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.236.32.23,172.236.32.35,172.236.32.30,172.236.32.28,172.236.32.32,172.236.32.33,172.236.32.27,172.236.32.37,172.236.32.29,172.236.32.34", + "au", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Kubernetes", "Cloud Firewall", + "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium Plans", "Placement + Group", "StackScripts", "NETINT Quadra T1U"], "status": "ok", "resolvers": {"ipv4": + "172.236.32.23,172.236.32.35,172.236.32.30,172.236.32.28,172.236.32.32,172.236.32.33,172.236.32.27,172.236.32.37,172.236.32.29,172.236.32.34", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "in-bom-2", "label": "Mumbai 2, IN", "country": - "in", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group"], - "status": "ok", "resolvers": {"ipv4": "172.236.171.41,172.236.171.42,172.236.171.25,172.236.171.44,172.236.171.26,172.236.171.45,172.236.171.24,172.236.171.43,172.236.171.27,172.236.171.28", + "in", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Cloud Firewall", "Vlans", "VPCs", + "Metadata", "Premium Plans", "Placement Group", "StackScripts"], "status": "ok", + "resolvers": {"ipv4": "172.236.171.41,172.236.171.42,172.236.171.25,172.236.171.44,172.236.171.26,172.236.171.45,172.236.171.24,172.236.171.43,172.236.171.27,172.236.171.28", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "de-fra-2", "label": "Frankfurt 2, DE", "country": - "de", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "GPU Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", - "Premium Plans", "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.236.203.9,172.236.203.16,172.236.203.19,172.236.203.15,172.236.203.17,172.236.203.11,172.236.203.18,172.236.203.14,172.236.203.13,172.236.203.12", + "de", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "GPU Linodes", "Kubernetes", "Cloud + Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", + "StackScripts", "NETINT Quadra T1U"], "status": "ok", "resolvers": {"ipv4": + "172.236.203.9,172.236.203.16,172.236.203.19,172.236.203.15,172.236.203.17,172.236.203.11,172.236.203.18,172.236.203.14,172.236.203.13,172.236.203.12", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "sg-sin-2", "label": "Singapore 2, SG", "country": - "sg", "capabilities": ["Linodes", "Block Storage Encryption", "Backups", "NodeBalancers", - "Block Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", - "Metadata", "Premium Plans", "Placement Group"], "status": "ok", "resolvers": - {"ipv4": "172.236.129.8,172.236.129.42,172.236.129.41,172.236.129.19,172.236.129.46,172.236.129.23,172.236.129.48,172.236.129.20,172.236.129.21,172.236.129.47", + "sg", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "GPU Linodes", "Kubernetes", "Cloud + Firewall", "Vlans", "VPCs", "Managed Databases", "Metadata", "Premium Plans", + "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "172.236.129.8,172.236.129.42,172.236.129.41,172.236.129.19,172.236.129.46,172.236.129.23,172.236.129.48,172.236.129.20,172.236.129.21,172.236.129.47", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "jp-tyo-3", "label": "Tokyo 3, JP", "country": - "jp", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "VPCs", "Metadata", "Premium Plans", - "Placement Group"], "status": "ok", "resolvers": {"ipv4": "172.237.4.15,172.237.4.19,172.237.4.17,172.237.4.21,172.237.4.16,172.237.4.18,172.237.4.23,172.237.4.24,172.237.4.20,172.237.4.14", + "jp", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Kubernetes", "Cloud Firewall", + "Vlans", "VPCs", "Metadata", "Premium Plans", "Placement Group", "StackScripts"], + "status": "ok", "resolvers": {"ipv4": "172.237.4.15,172.237.4.19,172.237.4.17,172.237.4.21,172.237.4.16,172.237.4.18,172.237.4.23,172.237.4.24,172.237.4.20,172.237.4.14", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-central", "label": "Dallas, TX", "country": - "us", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", "Managed - Databases", "Metadata", "Placement Group"], "status": "ok", "resolvers": {"ipv4": - "72.14.179.5, 72.14.188.5, 173.255.199.5, 66.228.53.5, 96.126.122.5, 96.126.124.5, - 96.126.127.5, 198.58.107.5, 198.58.111.5, 23.239.24.5", "ipv6": "1234::5678, + "us", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "72.14.179.5,72.14.188.5,173.255.199.5,66.228.53.5,96.126.122.5,96.126.124.5,96.126.127.5,198.58.107.5,198.58.111.5,23.239.24.5", + "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "us-west", "label": "Fremont, CA", "country": + "us", "capabilities": ["Linodes", "Block Storage Encryption", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Kubernetes", "Cloud Firewall", + "Vlans", "Block Storage Migrations", "Managed Databases", "Metadata", "Placement + Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "173.230.145.5, + 173.230.147.5, 173.230.155.5, 173.255.212.5, 173.255.219.5, 173.255.241.5, 173.255.243.5, + 173.255.244.5, 74.207.241.5, 74.207.242.5", "ipv6": "1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": - null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-west", - "label": "Fremont, CA", "country": "us", "capabilities": ["Linodes", "Backups", - "NodeBalancers", "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block - Storage Migrations", "Managed Databases", "Metadata", "Placement Group"], "status": - "ok", "resolvers": {"ipv4": "173.230.145.5, 173.230.147.5, 173.230.155.5, 173.255.212.5, - 173.255.219.5, 173.255.241.5, 173.255.243.5, 173.255.244.5, 74.207.241.5, 74.207.242.5", - "ipv6": "1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678"}, "placement_group_limits": - {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": - "core"}, {"id": "us-southeast", "label": "Atlanta, GA", "country": "us", "capabilities": - ["Linodes", "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU - Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", - "Managed Databases", "Metadata", "Placement Group"], "status": "ok", "resolvers": - {"ipv4": "74.207.231.5,173.230.128.5,173.230.129.5,173.230.136.5,173.230.140.5,66.228.59.5,66.228.62.5,50.116.35.5,50.116.41.5,23.239.18.5", + 1234::5678, 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": + null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-southeast", + "label": "Atlanta, GA", "country": "us", "capabilities": ["Linodes", "Disk Encryption", + "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", + "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", "Managed + Databases", "Metadata", "Placement Group", "StackScripts"], "status": "ok", + "resolvers": {"ipv4": "74.207.231.5,173.230.128.5,173.230.129.5,173.230.136.5,173.230.140.5,66.228.59.5,66.228.62.5,50.116.35.5,50.116.41.5,23.239.18.5", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "us-east", "label": "Newark, NJ", "country": "us", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "Block - Storage Migrations", "Managed Databases", "Metadata", "Placement Group"], "status": - "ok", "resolvers": {"ipv4": "66.228.42.5, 96.126.106.5, 50.116.53.5, 50.116.58.5, - 50.116.61.5, 50.116.62.5, 66.175.211.5, 97.107.133.4, 207.192.69.4, 207.192.69.5", - "ipv6": "1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, - 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678"}, "placement_group_limits": - {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": - "core"}, {"id": "eu-west", "label": "London, UK", "country": "gb", "capabilities": - ["Linodes", "Backups", "NodeBalancers", "Block Storage", "Kubernetes", "Cloud - Firewall", "Vlans", "Block Storage Migrations", "Managed Databases", "Metadata", - "Placement Group"], "status": "ok", "resolvers": {"ipv4": "178.79.182.5, 176.58.107.5, - 176.58.116.5, 176.58.121.5, 151.236.220.5, 212.71.252.5, 212.71.253.5, 109.74.192.20, - 109.74.193.20, 109.74.194.20", "ipv6": "1234::5678, 1234::5678, 1234::5678, + Storage Migrations", "Managed Databases", "Metadata", "Placement Group", "StackScripts"], + "status": "ok", "resolvers": {"ipv4": "66.228.42.5, 96.126.106.5, 50.116.53.5, + 50.116.58.5, 50.116.61.5, 50.116.62.5, 66.175.211.5, 97.107.133.4, 207.192.69.4, + 207.192.69.5", "ipv6": "1234::5678, 1234::5678, 1234::5678, 1234::5678, + 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678"}, + "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": + 5}, "site_type": "core"}, {"id": "eu-west", "label": "London, UK", "country": + "gb", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", + "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", "Metadata", + "Placement Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "178.79.182.5, + 176.58.107.5, 176.58.116.5, 176.58.121.5, 151.236.220.5, 212.71.252.5, 212.71.253.5, + 109.74.192.20, 109.74.193.20, 109.74.194.20", "ipv6": "1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, 1234::5678, - 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, - "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "ap-south", "label": - "Singapore, SG", "country": "sg", "capabilities": ["Linodes", "Backups", "NodeBalancers", - "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", - "Vlans", "Block Storage Migrations", "Managed Databases", "Metadata", "Placement - Group"], "status": "ok", "resolvers": {"ipv4": "139.162.11.5,139.162.13.5,139.162.14.5,139.162.15.5,139.162.16.5,139.162.21.5,139.162.27.5,103.3.60.18,103.3.60.19,103.3.60.20", + 1234::5678, 1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": + null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "ap-south", + "label": "Singapore, SG", "country": "sg", "capabilities": ["Linodes", "Backups", + "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", + "Cloud Firewall", "Vlans", "Block Storage Migrations", "Metadata", "Placement + Group", "StackScripts"], "status": "ok", "resolvers": {"ipv4": "139.162.11.5,139.162.13.5,139.162.14.5,139.162.15.5,139.162.16.5,139.162.21.5,139.162.27.5,103.3.60.18,103.3.60.19,103.3.60.20", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "eu-central", "label": "Frankfurt, DE", "country": "de", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", "Object Storage", "GPU Linodes", "Kubernetes", "Cloud Firewall", "Vlans", "Block - Storage Migrations", "Managed Databases", "Metadata", "Placement Group"], "status": - "ok", "resolvers": {"ipv4": "139.162.130.5,139.162.131.5,139.162.132.5,139.162.133.5,139.162.134.5,139.162.135.5,139.162.136.5,139.162.137.5,139.162.138.5,139.162.139.5", + Storage Migrations", "Managed Databases", "Metadata", "Placement Group", "StackScripts"], + "status": "ok", "resolvers": {"ipv4": "139.162.130.5,139.162.131.5,139.162.132.5,139.162.133.5,139.162.134.5,139.162.135.5,139.162.136.5,139.162.137.5,139.162.138.5,139.162.139.5", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}, {"id": "ap-northeast", "label": "Tokyo 2, JP", "country": - "jp", "capabilities": ["Linodes", "Backups", "NodeBalancers", "Block Storage", - "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", "Managed - Databases", "Metadata", "Placement Group"], "status": "ok", "resolvers": {"ipv4": - "139.162.66.5,139.162.67.5,139.162.68.5,139.162.69.5,139.162.70.5,139.162.71.5,139.162.72.5,139.162.73.5,139.162.74.5,139.162.75.5", + "jp", "capabilities": ["Linodes", "Disk Encryption", "Backups", "NodeBalancers", + "Block Storage", "Kubernetes", "Cloud Firewall", "Vlans", "Block Storage Migrations", + "Managed Databases", "Metadata", "Placement Group", "StackScripts"], "status": + "ok", "resolvers": {"ipv4": "139.162.66.5,139.162.67.5,139.162.68.5,139.162.69.5,139.162.70.5,139.162.71.5,139.162.72.5,139.162.73.5,139.162.74.5,139.162.75.5", "ipv6": "1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678,1234::5678"}, "placement_group_limits": {"maximum_pgs_per_customer": null, "maximum_linodes_per_pg": 5}, "site_type": "core"}], "page": 1, "pages": 1, "results": 31}' @@ -310,7 +271,7 @@ interactions: Content-Type: - application/json Expires: - - Tue, 05 Nov 2024 14:41:15 GMT + - Mon, 02 Dec 2024 14:43:50 GMT Pragma: - no-cache Strict-Transport-Security: @@ -329,14 +290,14 @@ interactions: X-Oauth-Scopes: - '*' X-Ratelimit-Limit: - - "800" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK code: 200 duration: "" - request: - body: '{"region":"ap-west","type":"g6-nanode-1","label":"go-test-ins-wo-disk-03at2019rkis","firewall_id":1136150,"booted":false}' + body: '{"region":"ap-west","type":"g6-nanode-1","label":"go-test-ins-wo-disk-4pz63s64i8uq","firewall_id":1279742,"booted":false}' form: {} headers: Accept: @@ -348,17 +309,17 @@ interactions: url: https://api.linode.com/v4beta/linode/instances method: POST response: - body: '{"id": 66615187, "label": "go-test-ins-wo-disk-03at2019rkis", "group": + body: '{"id": 67893544, "label": "go-test-ins-wo-disk-4pz63s64i8uq", "group": "", "status": "provisioning", "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", - "type": "g6-nanode-1", "ipv4": ["192.46.213.46"], "ipv6": "1234::5678/128", + "type": "g6-nanode-1", "ipv4": ["192.46.213.173"], "ipv6": "1234::5678/128", "image": null, "region": "ap-west", "site_type": "core", "specs": {"disk": 25600, - "memory": 1024, "vcpus": 1, "gpus": 0, "transfer": 1000}, "alerts": {"cpu": - 90, "network_in": 10, "network_out": 10, "transfer_quota": 80, "io": 10000}, - "backups": {"enabled": true, "available": false, "schedule": {"day": null, "window": - null}, "last_successful": null}, "hypervisor": "kvm", "watchdog_enabled": true, - "tags": [], "host_uuid": "bb03aee31fa7539cfeeeaf2fd3ea5d5c9f4d8e68", "has_user_data": - false, "placement_group": null, "disk_encryption": "disabled", "lke_cluster_id": - null, "capabilities": ["SMTP Enabled"]}' + "memory": 1024, "vcpus": 1, "gpus": 0, "transfer": 1000, "accelerated_devices": + 0}, "alerts": {"cpu": 90, "network_in": 10, "network_out": 10, "transfer_quota": + 80, "io": 10000}, "backups": {"enabled": true, "available": false, "schedule": + {"day": null, "window": null}, "last_successful": null}, "hypervisor": "kvm", + "watchdog_enabled": true, "tags": [], "host_uuid": "3f56a3df540f1c07c07d1bcb6b10cbaab2b6fb0a", + "has_user_data": false, "placement_group": null, "disk_encryption": "enabled", + "lke_cluster_id": null, "capabilities": ["SMTP Enabled"]}' headers: Access-Control-Allow-Credentials: - "true" @@ -381,7 +342,7 @@ interactions: Content-Type: - application/json Expires: - - Tue, 05 Nov 2024 14:41:16 GMT + - Mon, 02 Dec 2024 14:43:50 GMT Pragma: - no-cache Strict-Transport-Security: @@ -399,14 +360,14 @@ interactions: X-Oauth-Scopes: - '*' X-Ratelimit-Limit: - - "5" + - "8" X-Xss-Protection: - 1; mode=block status: 200 OK code: 200 duration: "" - request: - body: '{"label":"go-test-conf-9gl1xl346k8z","devices":{},"interfaces":null}' + body: '{"label":"go-test-conf-194m54f0ewrb","devices":{},"interfaces":null}' form: {} headers: Accept: @@ -415,10 +376,10 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/linode/instances/66615187/configs + url: https://api.linode.com/v4beta/linode/instances/67893544/configs method: POST response: - body: '{"id": 69931649, "label": "go-test-conf-9gl1xl346k8z", "helpers": {"updatedb_disabled": + body: '{"id": 71234066, "label": "go-test-conf-194m54f0ewrb", "helpers": {"updatedb_disabled": true, "distro": true, "modules_dep": true, "network": true, "devtmpfs_automount": true}, "kernel": "linode/latest-64bit", "comments": "", "memory_limit": 0, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "root_device": "/dev/sda", @@ -449,7 +410,7 @@ interactions: Content-Type: - application/json Expires: - - Tue, 05 Nov 2024 14:41:16 GMT + - Mon, 02 Dec 2024 14:43:51 GMT Pragma: - no-cache Strict-Transport-Security: @@ -466,7 +427,7 @@ interactions: X-Oauth-Scopes: - '*' X-Ratelimit-Limit: - - "800" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK @@ -482,7 +443,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/linode/instances/66615187/transfer/2024/11 + url: https://api.linode.com/v4beta/linode/instances/67893544/transfer/2024/12 method: GET response: body: '{"bytes_in": 0, "bytes_out": 0, "bytes_total": 0}' @@ -510,7 +471,7 @@ interactions: Content-Type: - application/json Expires: - - Tue, 05 Nov 2024 14:41:16 GMT + - Mon, 02 Dec 2024 14:43:51 GMT Pragma: - no-cache Strict-Transport-Security: @@ -528,7 +489,7 @@ interactions: X-Oauth-Scopes: - '*' X-Ratelimit-Limit: - - "800" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK @@ -544,7 +505,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/linode/instances/66615187 + url: https://api.linode.com/v4beta/linode/instances/67893544 method: DELETE response: body: '{}' @@ -572,7 +533,7 @@ interactions: Content-Type: - application/json Expires: - - Tue, 05 Nov 2024 14:41:18 GMT + - Mon, 02 Dec 2024 14:43:53 GMT Pragma: - no-cache Strict-Transport-Security: @@ -589,7 +550,7 @@ interactions: X-Oauth-Scopes: - '*' X-Ratelimit-Limit: - - "800" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK diff --git a/test/integration/fixtures/TestUserGrants_Update.yaml b/test/integration/fixtures/TestUserGrants_Update.yaml index 01d70d8e4..8e9a8a2c3 100644 --- a/test/integration/fixtures/TestUserGrants_Update.yaml +++ b/test/integration/fixtures/TestUserGrants_Update.yaml @@ -41,7 +41,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 25 Jul 2024 17:44:10 GMT + - Tue, 19 Nov 2024 20:30:59 GMT Pragma: - no-cache Strict-Transport-Security: @@ -56,19 +56,16 @@ interactions: - DENY - DENY X-Oauth-Scopes: - - account:read_write databases:read_write domains:read_write events:read_write - firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write - longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write - volumes:read_write vpc:read_write + - '*' X-Ratelimit-Limit: - - "400" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK code: 200 duration: "" - request: - body: '{"global":{"account_access":"read_only","add_databases":true,"add_domains":false,"add_firewalls":true,"add_images":true,"add_linodes":false,"add_longview":true,"add_nodebalancers":false,"add_stackscripts":true,"add_volumes":true,"cancel_account":false,"longview_subscription":false}}' + body: '{"global":{"account_access":"read_only","add_databases":true,"add_domains":false,"add_firewalls":true,"add_images":true,"add_linodes":false,"add_longview":true,"add_nodebalancers":false,"add_placement_groups":false,"add_stackscripts":true,"add_volumes":true,"add_vpcs":true,"cancel_account":false,"child_account_access":false,"longview_subscription":false}}' form: {} headers: Accept: @@ -80,42 +77,17 @@ interactions: url: https://api.linode.com/v4beta/account/users/linodegotest-updateusergrants/grants method: PUT response: - body: '{"linode": [{"id": 54748754, "label": "debian-us-ord", "permissions": null}, - {"id": 57328123, "label": "debian-us-central", "permissions": null}, {"id": - 60472044, "label": "linode60472044", "permissions": null}, {"id": 60939824, - "label": "ansible-test-471035164-updated", "permissions": null}, {"id": 61839386, - "label": "test-image-gen2", "permissions": null}, {"id": 61871792, "label": - "lke204599-296511-1ecf32b90000", "permissions": null}, {"id": 61871793, "label": - "lke204599-296511-5a5a335d0000", "permissions": null}, {"id": 61871794, "label": - "lke204599-296511-38c081dd0000", "permissions": null}], "nodebalancer": [{"id": - 600437, "label": "ansible-test-585459311", "permissions": null}], "domain": - [{"id": 2956594, "label": "example.clone-1713285844751924000-IntTestSDK.org", - "permissions": null}], "stackscript": [{"id": 1338923, "label": "test-stackscript", - "permissions": null}, {"id": 1424120, "label": "debian12-kube-8138f8e63a05", - "permissions": null}, {"id": 1424121, "label": "debian12-kube-8138f8e63a05", - "permissions": null}], "longview": [], "image": [{"id": 26425827, "label": "test_1721924280886354", - "permissions": null}, {"id": 26426164, "label": "test_1721925185088324", "permissions": - null}], "volume": [{"id": 1527342, "label": "ansible-test-563202246", "permissions": - null}], "firewall": [{"id": 433514, "label": "test-fw", "permissions": null}, - {"id": 624183, "label": "e2e-firewall-izUKXM", "permissions": null}, {"id": - 624308, "label": "e2e-firewall-svVoqB", "permissions": null}, {"id": 682410, - "label": "e2e-firewall-bucVPC", "permissions": null}, {"id": 682453, "label": - "e2e-firewall-WJsukx", "permissions": null}, {"id": 682477, "label": "e2e-firewall-IzEjvH", - "permissions": null}, {"id": 682500, "label": "e2e-firewall-QdxDkS", "permissions": - null}, {"id": 682505, "label": "e2e-firewall-KkroRq", "permissions": null}, - {"id": 682508, "label": "e2e-firewall-WPxzQk", "permissions": null}, {"id": - 682532, "label": "e2e-firewall-rBZhHt", "permissions": null}, {"id": 692740, - "label": "cloudfw-1721926678901029000", "permissions": null}, {"id": 692760, - "label": "cloudfw-1721927227347144000", "permissions": null}, {"id": 692763, - "label": "cloudfw-1721927316071520000", "permissions": null}, {"id": 692848, - "label": "cloudfw-1721929346146739000", "permissions": null}, {"id": 692854, - "label": "cloudfw-1721929441971780000", "permissions": null}], "database": [], - "vpc": [{"id": 41184, "label": "test-vpc", "permissions": null}, {"id": 56469, - "label": "my-vpc", "permissions": null}], "global": {"add_volumes": true, "add_images": - true, "add_stackscripts": true, "add_firewalls": true, "add_linodes": false, - "add_nodebalancers": false, "add_vpcs": false, "longview_subscription": false, - "add_databases": true, "add_longview": true, "child_account_access": null, "add_domains": - false, "account_access": "read_only", "cancel_account": false}}' + body: '{"linode": [], "nodebalancer": [{"id": 1051282, "label": "balancer12345", + "permissions": null}], "domain": [{"id": 3162745, "label": "example.clone-1731948401076807000-inttestsdk.org", + "permissions": null}], "stackscript": [], "longview": [], "image": [], "volume": + [], "firewall": [{"id": 1214534, "label": "cloudfw-1731954852210218000", "permissions": + null}, {"id": 1222347, "label": "e2e-fw-1732043552", "permissions": null}, {"id": + 1223238, "label": "cloudfw-1732048258071021000", "permissions": null}], "database": + [], "vpc": [], "global": {"add_nodebalancers": false, "child_account_access": + null, "add_longview": true, "add_volumes": true, "add_vpcs": true, "add_stackscripts": + true, "add_domains": false, "add_linodes": false, "add_images": true, "add_databases": + true, "longview_subscription": false, "add_firewalls": true, "account_access": + "read_only", "cancel_account": false}}' headers: Access-Control-Allow-Credentials: - "true" @@ -138,7 +110,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 25 Jul 2024 17:44:10 GMT + - Tue, 19 Nov 2024 20:31:00 GMT Pragma: - no-cache Strict-Transport-Security: @@ -154,12 +126,9 @@ interactions: - DENY - DENY X-Oauth-Scopes: - - account:read_write databases:read_write domains:read_write events:read_write - firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write - longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write - volumes:read_write vpc:read_write + - '*' X-Ratelimit-Limit: - - "400" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK @@ -203,7 +172,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 25 Jul 2024 17:44:10 GMT + - Tue, 19 Nov 2024 20:31:00 GMT Pragma: - no-cache Strict-Transport-Security: @@ -218,12 +187,9 @@ interactions: - DENY - DENY X-Oauth-Scopes: - - account:read_write databases:read_write domains:read_write events:read_write - firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write - longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write - volumes:read_write vpc:read_write + - '*' X-Ratelimit-Limit: - - "400" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK diff --git a/test/integration/fixtures/TestUserGrants_UpdateNoAccess.yaml b/test/integration/fixtures/TestUserGrants_UpdateNoAccess.yaml index a8bf5df74..a537f4d7f 100644 --- a/test/integration/fixtures/TestUserGrants_UpdateNoAccess.yaml +++ b/test/integration/fixtures/TestUserGrants_UpdateNoAccess.yaml @@ -41,7 +41,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 25 Jul 2024 17:44:11 GMT + - Tue, 19 Nov 2024 20:31:01 GMT Pragma: - no-cache Strict-Transport-Security: @@ -56,19 +56,16 @@ interactions: - DENY - DENY X-Oauth-Scopes: - - account:read_write databases:read_write domains:read_write events:read_write - firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write - longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write - volumes:read_write vpc:read_write + - '*' X-Ratelimit-Limit: - - "400" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK code: 200 duration: "" - request: - body: '{"global":{"account_access":null,"add_databases":false,"add_domains":false,"add_firewalls":false,"add_images":false,"add_linodes":false,"add_longview":false,"add_nodebalancers":false,"add_stackscripts":false,"add_volumes":false,"cancel_account":false,"longview_subscription":false}}' + body: '{"global":{"account_access":null,"add_databases":false,"add_domains":false,"add_firewalls":false,"add_images":false,"add_linodes":false,"add_longview":false,"add_nodebalancers":false,"add_placement_groups":false,"add_stackscripts":false,"add_volumes":false,"add_vpcs":false,"cancel_account":false,"child_account_access":false,"longview_subscription":false}}' form: {} headers: Accept: @@ -80,42 +77,17 @@ interactions: url: https://api.linode.com/v4beta/account/users/linodegotest-updateusergrantsna/grants method: PUT response: - body: '{"linode": [{"id": 54748754, "label": "debian-us-ord", "permissions": null}, - {"id": 57328123, "label": "debian-us-central", "permissions": null}, {"id": - 60472044, "label": "linode60472044", "permissions": null}, {"id": 60939824, - "label": "ansible-test-471035164-updated", "permissions": null}, {"id": 61839386, - "label": "test-image-gen2", "permissions": null}, {"id": 61871792, "label": - "lke204599-296511-1ecf32b90000", "permissions": null}, {"id": 61871793, "label": - "lke204599-296511-5a5a335d0000", "permissions": null}, {"id": 61871794, "label": - "lke204599-296511-38c081dd0000", "permissions": null}], "nodebalancer": [{"id": - 600437, "label": "ansible-test-585459311", "permissions": null}], "domain": - [{"id": 2956594, "label": "example.clone-1713285844751924000-IntTestSDK.org", - "permissions": null}], "stackscript": [{"id": 1338923, "label": "test-stackscript", - "permissions": null}, {"id": 1424120, "label": "debian12-kube-8138f8e63a05", - "permissions": null}, {"id": 1424121, "label": "debian12-kube-8138f8e63a05", - "permissions": null}], "longview": [], "image": [{"id": 26425827, "label": "test_1721924280886354", - "permissions": null}, {"id": 26426164, "label": "test_1721925185088324", "permissions": - null}], "volume": [{"id": 1527342, "label": "ansible-test-563202246", "permissions": - null}], "firewall": [{"id": 433514, "label": "test-fw", "permissions": null}, - {"id": 624183, "label": "e2e-firewall-izUKXM", "permissions": null}, {"id": - 624308, "label": "e2e-firewall-svVoqB", "permissions": null}, {"id": 682410, - "label": "e2e-firewall-bucVPC", "permissions": null}, {"id": 682453, "label": - "e2e-firewall-WJsukx", "permissions": null}, {"id": 682477, "label": "e2e-firewall-IzEjvH", - "permissions": null}, {"id": 682500, "label": "e2e-firewall-QdxDkS", "permissions": - null}, {"id": 682505, "label": "e2e-firewall-KkroRq", "permissions": null}, - {"id": 682508, "label": "e2e-firewall-WPxzQk", "permissions": null}, {"id": - 682532, "label": "e2e-firewall-rBZhHt", "permissions": null}, {"id": 692740, - "label": "cloudfw-1721926678901029000", "permissions": null}, {"id": 692760, - "label": "cloudfw-1721927227347144000", "permissions": null}, {"id": 692763, - "label": "cloudfw-1721927316071520000", "permissions": null}, {"id": 692848, - "label": "cloudfw-1721929346146739000", "permissions": null}, {"id": 692854, - "label": "cloudfw-1721929441971780000", "permissions": null}], "database": [], - "vpc": [{"id": 41184, "label": "test-vpc", "permissions": null}, {"id": 56469, - "label": "my-vpc", "permissions": null}], "global": {"add_volumes": false, "add_images": - false, "add_stackscripts": false, "add_firewalls": false, "add_linodes": false, - "add_nodebalancers": false, "add_vpcs": false, "longview_subscription": false, - "add_databases": false, "add_longview": false, "child_account_access": null, - "add_domains": false, "account_access": null, "cancel_account": false}}' + body: '{"linode": [], "nodebalancer": [{"id": 1051282, "label": "balancer12345", + "permissions": null}], "domain": [{"id": 3162745, "label": "example.clone-1731948401076807000-inttestsdk.org", + "permissions": null}], "stackscript": [], "longview": [], "image": [], "volume": + [], "firewall": [{"id": 1214534, "label": "cloudfw-1731954852210218000", "permissions": + null}, {"id": 1222347, "label": "e2e-fw-1732043552", "permissions": null}, {"id": + 1223238, "label": "cloudfw-1732048258071021000", "permissions": null}], "database": + [], "vpc": [], "global": {"add_firewalls": false, "add_stackscripts": false, + "add_volumes": false, "add_vpcs": false, "longview_subscription": false, "child_account_access": + null, "add_linodes": false, "add_databases": false, "add_domains": false, "add_images": + false, "add_longview": false, "add_nodebalancers": false, "account_access": + null, "cancel_account": false}}' headers: Access-Control-Allow-Credentials: - "true" @@ -138,7 +110,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 25 Jul 2024 17:44:11 GMT + - Tue, 19 Nov 2024 20:31:02 GMT Pragma: - no-cache Strict-Transport-Security: @@ -154,12 +126,9 @@ interactions: - DENY - DENY X-Oauth-Scopes: - - account:read_write databases:read_write domains:read_write events:read_write - firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write - longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write - volumes:read_write vpc:read_write + - '*' X-Ratelimit-Limit: - - "400" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK @@ -203,7 +172,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 25 Jul 2024 17:44:11 GMT + - Tue, 19 Nov 2024 20:31:02 GMT Pragma: - no-cache Strict-Transport-Security: @@ -218,12 +187,9 @@ interactions: - DENY - DENY X-Oauth-Scopes: - - account:read_write databases:read_write domains:read_write events:read_write - firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write - longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write - volumes:read_write vpc:read_write + - '*' X-Ratelimit-Limit: - - "400" + - "1600" X-Xss-Protection: - 1; mode=block status: 200 OK diff --git a/test/unit/account_user_grants_test.go b/test/unit/account_user_grants_test.go new file mode 100644 index 000000000..a539e53b6 --- /dev/null +++ b/test/unit/account_user_grants_test.go @@ -0,0 +1,144 @@ +package unit + +import ( + "context" + "github.com/linode/linodego" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAccountUserGrants_Get(t *testing.T) { + fixtureData, err := fixtures.GetFixture("account_user_grants_get") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("account/users/example-user/grants", fixtureData) + + grants, err := base.Client.GetUserGrants(context.Background(), "example-user") + if err != nil { + t.Fatalf("Error getting grants: %v", err) + } + + assert.Equal(t, 123, grants.Database[0].ID) + assert.Equal(t, "example-entity", grants.Database[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Database[0].Permissions) + assert.Equal(t, 123, grants.Domain[0].ID) + assert.Equal(t, "example-entity", grants.Domain[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Domain[0].Permissions) + assert.Equal(t, 123, grants.Firewall[0].ID) + assert.Equal(t, "example-entity", grants.Firewall[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Firewall[0].Permissions) + assert.Equal(t, 123, grants.Image[0].ID) + assert.Equal(t, "example-entity", grants.Image[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Image[0].Permissions) + assert.Equal(t, 123, grants.Linode[0].ID) + assert.Equal(t, "example-entity", grants.Linode[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Linode[0].Permissions) + assert.Equal(t, 123, grants.Longview[0].ID) + assert.Equal(t, "example-entity", grants.Longview[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Longview[0].Permissions) + assert.Equal(t, 123, grants.NodeBalancer[0].ID) + assert.Equal(t, "example-entity", grants.NodeBalancer[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.NodeBalancer[0].Permissions) + assert.Equal(t, 123, grants.PlacementGroup[0].ID) + assert.Equal(t, "example-entity", grants.PlacementGroup[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.PlacementGroup[0].Permissions) + assert.Equal(t, 123, grants.StackScript[0].ID) + assert.Equal(t, "example-entity", grants.StackScript[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.StackScript[0].Permissions) + assert.Equal(t, 123, grants.Volume[0].ID) + assert.Equal(t, "example-entity", grants.Volume[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Volume[0].Permissions) + assert.Equal(t, 123, grants.VPC[0].ID) + assert.Equal(t, "example-entity", grants.VPC[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.VPC[0].Permissions) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), *grants.Global.AccountAccess) + assert.Equal(t, true, grants.Global.AddDatabases) + assert.Equal(t, true, grants.Global.AddDomains) + assert.Equal(t, true, grants.Global.AddFirewalls) + assert.Equal(t, true, grants.Global.AddImages) + assert.Equal(t, true, grants.Global.AddLinodes) + assert.Equal(t, true, grants.Global.AddLongview) + assert.Equal(t, true, grants.Global.AddNodeBalancers) + assert.Equal(t, true, grants.Global.AddPlacementGroups) + assert.Equal(t, true, grants.Global.AddStackScripts) + assert.Equal(t, true, grants.Global.AddVolumes) + assert.Equal(t, true, grants.Global.AddVPCs) + assert.Equal(t, false, grants.Global.CancelAccount) + assert.Equal(t, true, grants.Global.ChildAccountAccess) + assert.Equal(t, true, grants.Global.LongviewSubscription) +} + +func TestAccountGrants_Update(t *testing.T) { + fixtureData, err := fixtures.GetFixture("account_user_grants_update") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + globalGrants := linodego.GlobalUserGrants{ + AccountAccess: nil, + } + + requestData := linodego.UserGrantsUpdateOptions{ + Global: globalGrants, + } + + base.MockPut("account/users/example-user/grants", fixtureData) + + grants, err := base.Client.UpdateUserGrants(context.Background(), "example-user", requestData) + assert.NoError(t, err) + + assert.Equal(t, 123, grants.Database[0].ID) + assert.Equal(t, "example-entity", grants.Database[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Database[0].Permissions) + assert.Equal(t, 123, grants.Domain[0].ID) + assert.Equal(t, "example-entity", grants.Domain[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Domain[0].Permissions) + assert.Equal(t, 123, grants.Firewall[0].ID) + assert.Equal(t, "example-entity", grants.Firewall[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Firewall[0].Permissions) + assert.Equal(t, 123, grants.Image[0].ID) + assert.Equal(t, "example-entity", grants.Image[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Image[0].Permissions) + assert.Equal(t, 123, grants.Linode[0].ID) + assert.Equal(t, "example-entity", grants.Linode[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Linode[0].Permissions) + assert.Equal(t, 123, grants.Longview[0].ID) + assert.Equal(t, "example-entity", grants.Longview[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Longview[0].Permissions) + assert.Equal(t, 123, grants.NodeBalancer[0].ID) + assert.Equal(t, "example-entity", grants.NodeBalancer[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.NodeBalancer[0].Permissions) + assert.Equal(t, 123, grants.PlacementGroup[0].ID) + assert.Equal(t, "example-entity", grants.PlacementGroup[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.PlacementGroup[0].Permissions) + assert.Equal(t, 123, grants.StackScript[0].ID) + assert.Equal(t, "example-entity", grants.StackScript[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.StackScript[0].Permissions) + assert.Equal(t, 123, grants.Volume[0].ID) + assert.Equal(t, "example-entity", grants.Volume[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.Volume[0].Permissions) + assert.Equal(t, 123, grants.VPC[0].ID) + assert.Equal(t, "example-entity", grants.VPC[0].Label) + assert.Equal(t, linodego.GrantPermissionLevel("read_only"), grants.VPC[0].Permissions) + assert.Equal(t, linodego.GrantPermissionLevel("read_write"), *grants.Global.AccountAccess) + assert.Equal(t, true, grants.Global.AddDatabases) + assert.Equal(t, true, grants.Global.AddDomains) + assert.Equal(t, true, grants.Global.AddFirewalls) + assert.Equal(t, true, grants.Global.AddImages) + assert.Equal(t, true, grants.Global.AddLinodes) + assert.Equal(t, true, grants.Global.AddLongview) + assert.Equal(t, true, grants.Global.AddNodeBalancers) + assert.Equal(t, true, grants.Global.AddPlacementGroups) + assert.Equal(t, true, grants.Global.AddStackScripts) + assert.Equal(t, true, grants.Global.AddVolumes) + assert.Equal(t, true, grants.Global.AddVPCs) + assert.Equal(t, false, grants.Global.CancelAccount) + assert.Equal(t, true, grants.Global.ChildAccountAccess) + assert.Equal(t, true, grants.Global.LongviewSubscription) +} diff --git a/test/unit/account_users_test.go b/test/unit/account_users_test.go new file mode 100644 index 000000000..61dd2517a --- /dev/null +++ b/test/unit/account_users_test.go @@ -0,0 +1,126 @@ +package unit + +import ( + "context" + "github.com/jarcoal/httpmock" + "github.com/linode/linodego" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAccountUsers_List(t *testing.T) { + fixtureData, err := fixtures.GetFixture("account_users_list") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("account/users", fixtureData) + + users, err := base.Client.ListUsers(context.Background(), nil) + if err != nil { + t.Fatalf("Error listing users: %v", err) + } + + assert.Equal(t, 1, len(users)) + user := users[0] + assert.Equal(t, "jperez@linode.com", user.Email) + assert.Equal(t, true, user.Restricted) + assert.Equal(t, []string{"home-pc", "laptop"}, user.SSHKeys) + assert.Equal(t, true, user.TFAEnabled) + assert.Equal(t, linodego.UserType("parent"), user.UserType) + assert.Equal(t, "jsmith", user.Username) + assert.Equal(t, "+5555555555", *user.VerifiedPhoneNumber) +} + +func TestAccountUsers_Get(t *testing.T) { + fixtureData, err := fixtures.GetFixture("account_users_get") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("account/users/jsmith", fixtureData) + + user, err := base.Client.GetUser(context.Background(), "jsmith") + if err != nil { + t.Fatalf("Error getting user: %v", err) + } + + assert.Equal(t, "jperez@linode.com", user.Email) + assert.Equal(t, true, user.Restricted) + assert.Equal(t, []string{"home-pc", "laptop"}, user.SSHKeys) + assert.Equal(t, true, user.TFAEnabled) + assert.Equal(t, linodego.UserType("parent"), user.UserType) + assert.Equal(t, "jsmith", user.Username) + assert.Equal(t, "+5555555555", *user.VerifiedPhoneNumber) +} + +func TestAccountUsers_Create(t *testing.T) { + fixtureData, err := fixtures.GetFixture("account_users_create") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + requestData := linodego.UserCreateOptions{ + Username: "example_user", + Email: "example_user@linode.com", + Restricted: true, + } + + base.MockPost("account/users", fixtureData) + + user, err := base.Client.CreateUser(context.Background(), requestData) + assert.NoError(t, err) + + assert.Equal(t, "example_user@linode.com", user.Email) + assert.Equal(t, true, user.Restricted) + assert.Equal(t, []string{"home-pc", "laptop"}, user.SSHKeys) + assert.Equal(t, true, user.TFAEnabled) + assert.Equal(t, "example_user", user.Username) + assert.Equal(t, "+5555555555", *user.VerifiedPhoneNumber) +} + +func TestAccountUsers_Update(t *testing.T) { + fixtureData, err := fixtures.GetFixture("account_users_update") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + restricted := true + + requestData := linodego.UserUpdateOptions{ + Username: "adevi", + Email: "jkowalski@linode.com", + Restricted: &restricted, + } + + base.MockPut("account/users/adevi", fixtureData) + + user, err := base.Client.UpdateUser(context.Background(), "adevi", requestData) + assert.NoError(t, err) + + assert.Equal(t, "jkowalski@linode.com", user.Email) + assert.Equal(t, true, user.Restricted) + assert.Equal(t, []string{"home-pc", "laptop"}, user.SSHKeys) + assert.Equal(t, true, user.TFAEnabled) + assert.Equal(t, linodego.UserType("parent"), user.UserType) + assert.Equal(t, "adevi", user.Username) + assert.Equal(t, "+5555555555", *user.VerifiedPhoneNumber) +} + +func TestAccountUsers_Delete(t *testing.T) { + client := createMockClient(t) + + httpmock.RegisterRegexpResponder("DELETE", mockRequestURL(t, "account/users/example-user"), httpmock.NewStringResponder(200, "{}")) + + if err := client.DeleteUser(context.Background(), "example-user"); err != nil { + t.Fatal(err) + } +} diff --git a/test/unit/fixtures/account_user_grants_get.json b/test/unit/fixtures/account_user_grants_get.json new file mode 100644 index 000000000..dc3913d1c --- /dev/null +++ b/test/unit/fixtures/account_user_grants_get.json @@ -0,0 +1,96 @@ +{ + "database": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "domain": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "firewall": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "global": { + "account_access": "read_only", + "add_databases": true, + "add_domains": true, + "add_firewalls": true, + "add_images": true, + "add_linodes": true, + "add_longview": true, + "add_nodebalancers": true, + "add_placement_groups": true, + "add_stackscripts": true, + "add_volumes": true, + "add_vpcs": true, + "cancel_account": false, + "child_account_access": true, + "longview_subscription": true + }, + "image": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "linode": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "longview": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "nodebalancer": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "placement_group": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "stackscript": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "volume": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "vpc": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ] +} \ No newline at end of file diff --git a/test/unit/fixtures/account_user_grants_update.json b/test/unit/fixtures/account_user_grants_update.json new file mode 100644 index 000000000..52c06a926 --- /dev/null +++ b/test/unit/fixtures/account_user_grants_update.json @@ -0,0 +1,96 @@ +{ + "database": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "domain": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "firewall": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "global": { + "account_access": "read_write", + "add_databases": true, + "add_domains": true, + "add_firewalls": true, + "add_images": true, + "add_linodes": true, + "add_longview": true, + "add_nodebalancers": true, + "add_placement_groups": true, + "add_stackscripts": true, + "add_volumes": true, + "add_vpcs": true, + "cancel_account": false, + "child_account_access": true, + "longview_subscription": true + }, + "image": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "linode": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "longview": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "nodebalancer": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "placement_group": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "stackscript": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "volume": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ], + "vpc": [ + { + "id": 123, + "label": "example-entity", + "permissions": "read_only" + } + ] +} \ No newline at end of file diff --git a/test/unit/fixtures/account_users_create.json b/test/unit/fixtures/account_users_create.json new file mode 100644 index 000000000..883ee2949 --- /dev/null +++ b/test/unit/fixtures/account_users_create.json @@ -0,0 +1,16 @@ +{ + "email": "example_user@linode.com", + "last_login": { + "login_datetime": "2018-01-01T01:01:01", + "status": "successful" + }, + "password_created": "2018-01-01T01:01:01", + "restricted": true, + "ssh_keys": [ + "home-pc", + "laptop" + ], + "tfa_enabled": true, + "username": "example_user", + "verified_phone_number": "+5555555555" +} \ No newline at end of file diff --git a/test/unit/fixtures/account_users_get.json b/test/unit/fixtures/account_users_get.json new file mode 100644 index 000000000..245574b1c --- /dev/null +++ b/test/unit/fixtures/account_users_get.json @@ -0,0 +1,17 @@ +{ + "email": "jperez@linode.com", + "last_login": { + "login_datetime": "2018-01-01T01:01:01", + "status": "successful" + }, + "password_created": "2018-01-01T01:01:01", + "restricted": true, + "ssh_keys": [ + "home-pc", + "laptop" + ], + "tfa_enabled": true, + "user_type": "parent", + "username": "jsmith", + "verified_phone_number": "+5555555555" +} \ No newline at end of file diff --git a/test/unit/fixtures/account_users_list.json b/test/unit/fixtures/account_users_list.json new file mode 100644 index 000000000..dbbb1c951 --- /dev/null +++ b/test/unit/fixtures/account_users_list.json @@ -0,0 +1,24 @@ +{ + "data": [ + { + "email": "jperez@linode.com", + "last_login": { + "login_datetime": "2018-01-01T01:01:01", + "status": "successful" + }, + "password_created": "2018-01-01T01:01:01", + "restricted": true, + "ssh_keys": [ + "home-pc", + "laptop" + ], + "tfa_enabled": true, + "user_type": "parent", + "username": "jsmith", + "verified_phone_number": "+5555555555" + } + ], + "page": 1, + "pages": 1, + "results": 1 +} \ No newline at end of file diff --git a/test/unit/fixtures/account_users_update.json b/test/unit/fixtures/account_users_update.json new file mode 100644 index 000000000..71b047318 --- /dev/null +++ b/test/unit/fixtures/account_users_update.json @@ -0,0 +1,17 @@ +{ + "email": "jkowalski@linode.com", + "last_login": { + "login_datetime": "2018-01-01T01:01:01", + "status": "successful" + }, + "password_created": "2018-01-01T01:01:01", + "restricted": true, + "ssh_keys": [ + "home-pc", + "laptop" + ], + "tfa_enabled": true, + "user_type": "parent", + "username": "adevi", + "verified_phone_number": "+5555555555" +} \ No newline at end of file