Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,3 @@
**What are the steps to reproduce the issue or verify the changes?**

**How do I run the relevant unit/integration tests?**

## 📷 Preview

**If applicable, include a screenshot or code snippet of this change. Otherwise, please remove this section.**
10 changes: 9 additions & 1 deletion .github/workflows/e2e-test-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ on:
pull_request_number:
description: 'The number of the PR.'
required: false
test_report_upload:
description: 'Indicates whether to upload the test report to object storage. Defaults to "false"'
required: false
default: 'false'
type: choice
options:
- 'true'
- 'false'

name: PR E2E Tests

Expand Down Expand Up @@ -101,7 +109,7 @@ jobs:
LINODE_TOKEN: ${{ secrets.LINODE_TOKEN }}

- name: Upload test results
if: always()
if: always() && github.repository == 'linode/linode_api4-python' && (github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && inputs.test_report_upload == 'true'))
run: |
filename=$(ls | grep -E '^[0-9]{12}_sdk_test_report\.xml$')
python3 e2e_scripts/tod_scripts/xml_to_obj_storage/scripts/add_gha_info_to_xml.py \
Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ on:
options:
- 'true'
- 'false'
test_report_upload:
description: 'Indicates whether to upload the test report to object storage. Defaults to "false"'
type: choice
required: false
default: 'false'
options:
- 'true'
- 'false'
push:
branches:
- main
Expand Down Expand Up @@ -172,7 +180,8 @@ jobs:
process-upload-report:
runs-on: ubuntu-latest
needs: [integration-tests]
if: always() && github.repository == 'linode/linode_api4-python' # Run even if integration tests fail and only on main repository
# Run even if integration tests fail on main repository AND push event OR test_report_upload is true in case of manual run
if: always() && github.repository == 'linode/linode_api4-python' && (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.test_report_upload == 'true'))
outputs:
summary: ${{ steps.set-test-summary.outputs.summary }}

Expand Down Expand Up @@ -271,4 +280,4 @@ jobs:
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
thread_ts: "${{ steps.main_message.outputs.ts }}"
text: "${{ needs.process-upload-report.outputs.summary }}"
text: "${{ needs.process-upload-report.outputs.summary }}"
2 changes: 0 additions & 2 deletions linode_api4/groups/linode.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,6 @@ def instance_create(
:type network_helper: bool
:param maintenance_policy: The slug of the maintenance policy to apply during maintenance.
If not provided, the default policy (linode/migrate) will be applied.
NOTE: This field is in beta and may only
function if base_url is set to `https://api.linode.com/v4beta`.
:type maintenance_policy: str

:returns: A new Instance object, or a tuple containing the new Instance and
Expand Down
11 changes: 10 additions & 1 deletion linode_api4/groups/lke.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ def cluster_create(
self,
region,
label,
node_pools,
kube_version,
node_pools: Optional[list] = None,
control_plane: Union[
LKEClusterControlPlaneOptions, Dict[str, Any]
] = None,
Expand Down Expand Up @@ -119,6 +119,15 @@ def cluster_create(
:returns: The new LKE Cluster
:rtype: LKECluster
"""
if node_pools is None:
node_pools = []

if len(node_pools) == 0 and (
tier is None or tier.lower() != "enterprise"
):
raise ValueError(
"LKE standard clusters must have at least one node pool."
)

params = {
"label": label,
Expand Down
2 changes: 0 additions & 2 deletions linode_api4/groups/maintenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ class MaintenanceGroup(Group):

def maintenance_policies(self):
"""
.. note:: This endpoint is in beta. This will only function if base_url is set to `https://api.linode.com/v4beta`.

Returns a collection of MaintenancePolicy objects representing
available maintenance policies that can be applied to Linodes

Expand Down
2 changes: 1 addition & 1 deletion linode_api4/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .dbase import DerivedBase
from .serializable import JSONObject
from .filtering import and_, or_
from .region import Region
from .region import Region, Capability
from .image import Image
from .linode import *
from .linode_interfaces import *
Expand Down
6 changes: 2 additions & 4 deletions linode_api4/objects/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,7 @@ class AccountSettings(Base):
"object_storage": Property(),
"backups_enabled": Property(mutable=True),
"interfaces_for_new_linodes": Property(mutable=True),
"maintenance_policy": Property(
mutable=True
), # Note: This field is only available when using v4beta.
"maintenance_policy": Property(mutable=True),
}


Expand Down Expand Up @@ -249,7 +247,7 @@ class Event(Base):
"duration": Property(),
"secondary_entity": Property(),
"message": Property(),
"maintenance_policy_set": Property(), # Note: This field is only available when using v4beta.
"maintenance_policy_set": Property(),
"description": Property(),
"source": Property(),
"not_before": Property(is_datetime=True),
Expand Down
4 changes: 1 addition & 3 deletions linode_api4/objects/linode.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,9 +800,7 @@ class Instance(Base):
"lke_cluster_id": Property(),
"capabilities": Property(unordered=True),
"interface_generation": Property(),
"maintenance_policy": Property(
mutable=True
), # Note: This field is only available when using v4beta.
"maintenance_policy": Property(mutable=True),
"locks": Property(unordered=True),
}

Expand Down
6 changes: 3 additions & 3 deletions linode_api4/objects/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class LockType(StrEnum):
"""
LockType defines valid values for resource lock types.

API Documentation: https://techdocs.akamai.com/linode-api/reference/post-lock
API Documentation: TBD
"""

cannot_delete = "cannot_delete"
Expand All @@ -22,7 +22,7 @@ class LockEntity(JSONObject):
"""
Represents the entity that is locked.

API Documentation: https://techdocs.akamai.com/linode-api/reference/get-lock
API Documentation: TBD
"""

id: int = 0
Expand All @@ -35,7 +35,7 @@ class Lock(Base):
"""
A resource lock that prevents deletion or modification of a resource.

API Documentation: https://techdocs.akamai.com/linode-api/reference/get-lock
API Documentation: TBD
"""

api_endpoint = "/locks/{id}"
Expand Down
1 change: 1 addition & 0 deletions linode_api4/objects/nodebalancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ class NodeBalancer(Base):
"transfer": Property(),
"tags": Property(mutable=True, unordered=True),
"client_udp_sess_throttle": Property(mutable=True),
"locks": Property(unordered=True),
}

# create derived objects
Expand Down
62 changes: 62 additions & 0 deletions linode_api4/objects/region.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,68 @@

from linode_api4.errors import UnexpectedResponseError
from linode_api4.objects.base import Base, JSONObject, Property
from linode_api4.objects.serializable import StrEnum


class Capability(StrEnum):
"""
An enum class that represents the capabilities that Linode offers
across different regions and services.

These capabilities indicate what services are available in each data center.
"""

linodes = "Linodes"
nodebalancers = "NodeBalancers"
block_storage = "Block Storage"
object_storage = "Object Storage"
object_storage_regions = "Object Storage Access Key Regions"
object_storage_endpoint_types = "Object Storage Endpoint Types"
lke = "Kubernetes"
lke_ha_controlplanes = "LKE HA Control Planes"
lke_e = "Kubernetes Enterprise"
firewall = "Cloud Firewall"
gpu = "GPU Linodes"
vlans = "Vlans"
vpcs = "VPCs"
vpcs_extra = "VPCs Extra"
machine_images = "Machine Images"
dbaas = "Managed Databases"
dbaas_beta = "Managed Databases Beta"
bs_migrations = "Block Storage Migrations"
metadata = "Metadata"
premium_plans = "Premium Plans"
edge_plans = "Edge Plans"
distributed_plans = "Distributed Plans"
lke_control_plane_acl = "LKE Network Access Control List (IP ACL)"
aclb = "Akamai Cloud Load Balancer"
support_ticket_severity = "Support Ticket Severity"
backups = "Backups"
placement_group = "Placement Group"
disk_encryption = "Disk Encryption"
la_disk_encryption = "LA Disk Encryption"
akamai_ram_protection = "Akamai RAM Protection"
blockstorage_encryption = "Block Storage Encryption"
blockstorage_perf_b1 = "Block Storage Performance B1"
blockstorage_perf_b1_default = "Block Storage Performance B1 Default"
aclp = "Akamai Cloud Pulse"
aclp_logs = "Akamai Cloud Pulse Logs"
aclp_logs_lkee = "Akamai Cloud Pulse Logs LKE-E Audit"
aclp_logs_dc_lkee = "ACLP Logs Datacenter LKE-E"
smtp_enabled = "SMTP Enabled"
stackscripts = "StackScripts"
vpu = "NETINT Quadra T1U"
linode_interfaces = "Linode Interfaces"
maintenance_policy = "Maintenance Policy"
vpc_dual_stack = "VPC Dual Stack"
vpc_ipv6_stack = "VPC IPv6 Stack"
nlb = "Network LoadBalancer"
natgateway = "NAT Gateway"
lke_e_byovpc = "Kubernetes Enterprise BYO VPC"
lke_e_stacktype = "Kubernetes Enterprise Dual Stack"
ruleset = "Cloud Firewall Rule Set"
prefixlists = "Cloud Firewall Prefix Lists"
current_prefixlists = "Cloud Firewall Prefix List Current References"


@dataclass
Expand Down
6 changes: 4 additions & 2 deletions test/fixtures/nodebalancers.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"updated": "2018-01-01T00:01:01",
"label": "balancer123456",
"client_conn_throttle": 0,
"tags": ["something"]
"tags": ["something"],
"locks": ["cannot_delete_with_subresources"]
},
{
"created": "2018-01-01T00:01:01",
Expand All @@ -22,7 +23,8 @@
"updated": "2018-01-01T00:01:01",
"label": "balancer123457",
"client_conn_throttle": 0,
"tags": []
"tags": [],
"locks": []
}
],
"results": 2,
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/nodebalancers_123456.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@
"client_conn_throttle": 0,
"tags": [
"something"
],
"locks": [
"cannot_delete_with_subresources"
]
}
4 changes: 2 additions & 2 deletions test/integration/filters/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ def lke_cluster_instance(test_linode_client):

region = get_region(test_linode_client, {"Kubernetes", "Disk Encryption"})

node_pools = test_linode_client.lke.node_pool(node_type, 3)
node_pool = test_linode_client.lke.node_pool(node_type, 3)
label = get_test_label() + "_cluster"

cluster = test_linode_client.lke.cluster_create(
region, label, node_pools, version
region, label, version, [node_pool]
)

yield cluster
Expand Down
5 changes: 3 additions & 2 deletions test/integration/filters/model_filters_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@ def test_linode_type_model_filter(test_linode_client):

def test_lke_cluster_model_filter(test_linode_client, lke_cluster_instance):
client = test_linode_client
lke_cluster = lke_cluster_instance

filtered_cluster = client.lke.clusters(
LKECluster.label.contains(lke_cluster_instance.label)
LKECluster.label.contains(lke_cluster.label)
)

assert filtered_cluster[0].id == lke_cluster_instance.id
assert filtered_cluster[0].id == lke_cluster.id


def test_networking_firewall_model_filter(
Expand Down
6 changes: 3 additions & 3 deletions test/integration/linode_client/test_linode_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,10 @@ def test_cluster_create_with_api_objects(test_linode_client):
node_type = client.linode.types()[1] # g6-standard-1
version = client.lke.versions()[0]
region = get_region(client, {"Kubernetes"})
node_pools = client.lke.node_pool(node_type, 3)
node_pool = client.lke.node_pool(node_type, 3)
label = get_test_label()

cluster = client.lke.cluster_create(region, label, node_pools, version)
cluster = client.lke.cluster_create(region, label, version, [node_pool])

assert cluster.region.id == region.id
assert cluster.k8s_version.id == version.id
Expand All @@ -350,8 +350,8 @@ def test_fails_to_create_cluster_with_invalid_version(test_linode_client):
cluster = client.lke.cluster_create(
region,
"example-cluster",
{"type": "g6-standard-1", "count": 3},
invalid_version,
{"type": "g6-standard-1", "count": 3},
)
except ApiError as e:
assert "not valid" in str(e.json)
Expand Down
3 changes: 1 addition & 2 deletions test/integration/models/linode/test_linode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1101,8 +1101,7 @@ def test_delete_interface_containing_vpc(

def test_create_linode_with_maintenance_policy(test_linode_client):
client = test_linode_client
# TODO: Replace with random region after GA
region = "ap-south"
region = get_region(client, {"Linodes", "Cloud Firewall"}, site_type="core")
label = get_test_label()

policies = client.maintenance.maintenance_policies()
Expand Down
10 changes: 5 additions & 5 deletions test/integration/models/lke/test_lke.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def lke_cluster(test_linode_client):
label = get_test_label() + "_cluster"

cluster = test_linode_client.lke.cluster_create(
region, label, node_pools, version
region, label, version, node_pools
)

yield cluster
Expand All @@ -57,8 +57,8 @@ def lke_cluster_with_acl(test_linode_client):
cluster = test_linode_client.lke.cluster_create(
region,
label,
node_pools,
version,
node_pools,
control_plane=LKEClusterControlPlaneOptions(
acl=LKEClusterControlPlaneACLOptions(
enabled=True,
Expand Down Expand Up @@ -103,7 +103,7 @@ def lke_cluster_with_labels_and_taints(test_linode_client):
label = get_test_label() + "_cluster"

cluster = test_linode_client.lke.cluster_create(
region, label, node_pools, version
region, label, version, node_pools
)

yield cluster
Expand All @@ -124,8 +124,8 @@ def lke_cluster_with_apl(test_linode_client):
cluster = test_linode_client.lke.cluster_create(
region,
label,
node_pools,
version,
node_pools,
control_plane=LKEClusterControlPlaneOptions(
high_availability=True,
),
Expand Down Expand Up @@ -160,8 +160,8 @@ def lke_cluster_enterprise(e2e_test_firewall, test_linode_client):
cluster = test_linode_client.lke.cluster_create(
region,
label,
node_pools,
version,
node_pools,
tier="enterprise",
)

Expand Down
Loading
Loading