Skip to content

Commit 416f7a9

Browse files
authored
Merge pull request #691 from linode/dev
Release 5.44.0
2 parents da9953c + fcc41e5 commit 416f7a9

41 files changed

Lines changed: 731 additions & 240 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/clean-release-notes.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212

1313
steps:
1414
- name: Remove ticket prefixes from release notes
15-
uses: actions/github-script@v8
15+
uses: actions/github-script@v9
1616
with:
1717
script: |
1818
const release = context.payload.release;

.github/workflows/dependency-review.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ jobs:
1313
- name: 'Checkout repository'
1414
uses: actions/checkout@v6
1515
- name: 'Dependency Review'
16-
uses: actions/dependency-review-action@v4
16+
uses: actions/dependency-review-action@v5
1717
with:
1818
comment-summary-in-pr: on-failure

.github/workflows/e2e-test-pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ jobs:
123123
LINODE_CLI_OBJ_ACCESS_KEY: ${{ secrets.LINODE_CLI_OBJ_ACCESS_KEY }}
124124
LINODE_CLI_OBJ_SECRET_KEY: ${{ secrets.LINODE_CLI_OBJ_SECRET_KEY }}
125125

126-
- uses: actions/github-script@v8
126+
- uses: actions/github-script@v9
127127
id: update-check-run
128128
if: ${{ inputs.pull_request_number != '' && fromJson(steps.commit-hash.outputs.data).repository.pullRequest.headRef.target.oid == inputs.sha }}
129129
env:

linode_api4/groups/linode.py

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ def instance_create(
162162
interface_generation: Optional[Union[InterfaceGeneration, str]] = None,
163163
network_helper: Optional[bool] = None,
164164
maintenance_policy: Optional[str] = None,
165+
root_pass: Optional[str] = None,
166+
kernel: Optional[str] = None,
167+
boot_size: Optional[int] = None,
168+
authorized_users: Optional[List[str]] = None,
165169
**kwargs,
166170
):
167171
"""
@@ -172,27 +176,26 @@ def instance_create(
172176
To create an Instance from an :any:`Image`, call `instance_create` with
173177
a :any:`Type`, a :any:`Region`, and an :any:`Image`. All three of
174178
these fields may be provided as either the ID or the appropriate object.
175-
In this mode, a root password will be generated and returned with the
176-
new Instance object.
179+
When an Image is provided, at least one of ``root_pass``, ``authorized_users``, or
180+
``authorized_keys`` must also be given.
177181
178182
For example::
179183
180-
new_linode, password = client.linode.instance_create(
184+
new_linode = client.linode.instance_create(
181185
"g6-standard-2",
182186
"us-east",
183-
image="linode/debian9")
187+
image="linode/debian13",
188+
root_pass="aComplex@Password123")
184189
185190
ltype = client.linode.types().first()
186191
region = client.regions().first()
187192
image = client.images().first()
188193
189-
another_linode, password = client.linode.instance_create(
194+
another_linode = client.linode.instance_create(
190195
ltype,
191196
region,
192-
image=image)
193-
194-
To output the password from the above example:
195-
print(password)
197+
image=image,
198+
authorized_keys="ssh-rsa AAAA")
196199
197200
To output the first IPv4 address of the new Linode:
198201
print(new_linode.ipv4[0])
@@ -210,10 +213,11 @@ def instance_create(
210213
211214
stackscript = StackScript(client, 10079)
212215
213-
new_linode, password = client.linode.instance_create(
216+
new_linode = client.linode.instance_create(
214217
"g6-standard-2",
215218
"us-east",
216-
image="linode/debian9",
219+
image="linode/debian13",
220+
root_pass="aComplex@Password123",
217221
stackscript=stackscript,
218222
stackscript_data={"gh_username": "example"})
219223
@@ -244,10 +248,11 @@ def instance_create(
244248
To create a new Instance with explicit interfaces, provide list of
245249
LinodeInterfaceOptions objects or dicts to the "interfaces" field::
246250
247-
linode, password = client.linode.instance_create(
251+
linode = client.linode.instance_create(
248252
"g6-standard-1",
249253
"us-mia",
250254
image="linode/ubuntu24.04",
255+
root_pass="aComplex@Password123",
251256
252257
# This can be configured as an account-wide default
253258
interface_generation=InterfaceGeneration.LINODE,
@@ -280,10 +285,14 @@ def instance_create(
280285
:type ltype: str or Type
281286
:param region: The Region in which we are creating the Instance
282287
:type region: str or Region
283-
:param image: The Image to deploy to this Instance. If this is provided
284-
and no root_pass is given, a password will be generated
285-
and returned along with the new Instance.
288+
:param image: The Image to deploy to this Instance. If this is provided,
289+
at least one of root_pass, authorized_users, or authorized_keys must also be
290+
provided.
286291
:type image: str or Image
292+
:param root_pass: The root password for the new Instance. Required when
293+
an image is provided and neither authorized_users nor
294+
authorized_keys are given.
295+
:type root_pass: str
287296
:param stackscript: The StackScript to deploy to the new Instance. If
288297
provided, "image" is required and must be compatible
289298
with the chosen StackScript.
@@ -300,6 +309,11 @@ def instance_create(
300309
be a single key, or a path to a file containing
301310
the key.
302311
:type authorized_keys: list or str
312+
:param authorized_users: A list of usernames whose keys should be installed
313+
as trusted for the root user. These user's keys
314+
should already be set up, see :any:`ProfileGroup.ssh_keys`
315+
for details.
316+
:type authorized_users: list[str]
303317
:param label: The display label for the new Instance
304318
:type label: str
305319
:param group: The display group for the new Instance
@@ -335,26 +349,39 @@ def instance_create(
335349
:param maintenance_policy: The slug of the maintenance policy to apply during maintenance.
336350
If not provided, the default policy (linode/migrate) will be applied.
337351
:type maintenance_policy: str
338-
339-
:returns: A new Instance object, or a tuple containing the new Instance and
340-
the generated password.
341-
:rtype: Instance or tuple(Instance, str)
352+
:param kernel: The kernel to boot the Instance with. If provided, this will be used as the
353+
kernel for the default configuration profile.
354+
:type kernel: str
355+
:param boot_size: The size of the boot disk in MB. If provided, this will be used to create
356+
the boot disk for the Instance.
357+
:type boot_size: int
358+
359+
:returns: A new Instance object
360+
:rtype: Instance
342361
:raises ApiError: If contacting the API fails
343362
:raises UnexpectedResponseError: If the API response is somehow malformed.
344363
This usually indicates that you are using
345364
an outdated library.
346365
"""
347366

348-
ret_pass = None
349-
if image and not "root_pass" in kwargs:
350-
ret_pass = Instance.generate_root_password()
351-
kwargs["root_pass"] = ret_pass
367+
if (
368+
image
369+
and not root_pass
370+
and not authorized_keys
371+
and not authorized_users
372+
):
373+
raise ValueError(
374+
"When creating an Instance from an Image, at least one of "
375+
"root_pass, authorized_users, or authorized_keys must be provided."
376+
)
352377

353378
params = {
354379
"type": ltype,
355380
"region": region,
356381
"image": image,
382+
"root_pass": root_pass,
357383
"authorized_keys": load_and_validate_keys(authorized_keys),
384+
"authorized_users": authorized_users,
358385
# These will automatically be flattened below
359386
"firewall_id": firewall,
360387
"backup_id": backup,
@@ -372,6 +399,8 @@ def instance_create(
372399
"interfaces": interfaces,
373400
"interface_generation": interface_generation,
374401
"network_helper": network_helper,
402+
"kernel": kernel,
403+
"boot_size": boot_size,
375404
}
376405

377406
params.update(kwargs)
@@ -386,10 +415,7 @@ def instance_create(
386415
"Unexpected response when creating linode!", json=result
387416
)
388417

389-
l = Instance(self.client, result["id"], result)
390-
if not ret_pass:
391-
return l
392-
return l, ret_pass
418+
return Instance(self.client, result["id"], result)
393419

394420
@staticmethod
395421
def build_instance_metadata(user_data=None, encode_user_data=True):
@@ -398,10 +424,11 @@ def build_instance_metadata(user_data=None, encode_user_data=True):
398424
the :any:`instance_create` method. This helper can also be used
399425
when cloning and rebuilding Instances.
400426
**Creating an Instance with User Data**::
401-
new_linode, password = client.linode.instance_create(
427+
new_linode = client.linode.instance_create(
402428
"g6-standard-2",
403429
"us-east",
404430
image="linode/ubuntu22.04",
431+
root_pass="aComplex@Password123",
405432
metadata=client.linode.build_instance_metadata(user_data="myuserdata")
406433
)
407434
:param user_data: User-defined data to provide to the Linode Instance through

linode_api4/groups/lock.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def __call__(self, *filters):
2424
2525
locks = client.locks()
2626
27-
API Documentation: TBD
27+
API Documentation: https://techdocs.akamai.com/linode-api/reference/get-resource-locks
2828
2929
:param filters: Any number of filters to apply to this query.
3030
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
@@ -44,7 +44,7 @@ def create(
4444
"""
4545
Creates a new Resource Lock for the specified entity.
4646
47-
API Documentation: TBD
47+
API Documentation: https://techdocs.akamai.com/linode-api/reference/post-resource-lock
4848
4949
:param entity_type: The type of entity to lock (e.g., "linode").
5050
:type entity_type: str

linode_api4/groups/networking.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,10 @@ def ip_addresses_assign(self, assignments, region):
452452
:param assignments: Any number of assignments to make. See
453453
:any:`IPAddress.to` for details on how to construct
454454
assignments.
455-
:type assignments: dct
455+
:type assignments: list
456456
"""
457457

458-
for a in assignments["assignments"]:
458+
for a in assignments:
459459
if not "address" in a or not "linode_id" in a:
460460
raise ValueError("Invalid assignment: {}".format(a))
461461

linode_api4/groups/object_storage.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ObjectStorageACL,
2020
ObjectStorageBucket,
2121
ObjectStorageCluster,
22+
ObjectStorageGlobalQuota,
2223
ObjectStorageKeyPermission,
2324
ObjectStorageKeys,
2425
ObjectStorageQuota,
@@ -533,3 +534,18 @@ def quotas(self, *filters):
533534
:rtype: PaginatedList of ObjectStorageQuota
534535
"""
535536
return self.client._get_and_filter(ObjectStorageQuota, *filters)
537+
538+
def global_quotas(self, *filters):
539+
"""
540+
Lists the active account-level Object Storage quotas applied to your account.
541+
542+
API Documentation: TBD
543+
544+
:param filters: Any number of filters to apply to this query.
545+
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
546+
for more details on filtering.
547+
548+
:returns: A list of account-level Object Storage Quotas that matched the query.
549+
:rtype: PaginatedList of ObjectStorageGlobalQuota
550+
"""
551+
return self.client._get_and_filter(ObjectStorageGlobalQuota, *filters)

linode_api4/objects/database.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
from dataclasses import dataclass, field
22
from typing import Optional
33

4-
from linode_api4.objects import (
5-
Base,
6-
JSONObject,
7-
MappedObject,
8-
Property,
9-
)
4+
from linode_api4.objects import Base, JSONObject, MappedObject, Property
105

116

127
class DatabaseType(Base):

0 commit comments

Comments
 (0)