Skip to content
Open
Show file tree
Hide file tree
Changes from all 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