Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/c7n_gcp/resources/compute.py: 72%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

336 statements  

1# Copyright The Cloud Custodian Authors. 

2# SPDX-License-Identifier: Apache-2.0 

3 

4import re 

5 

6from datetime import datetime 

7 

8from c7n.utils import local_session, type_schema 

9 

10from c7n_gcp.actions import MethodAction 

11from c7n_gcp.filters import IamPolicyFilter 

12from c7n_gcp.filters.iampolicy import IamPolicyValueFilter 

13from c7n_gcp.provider import resources 

14from c7n_gcp.query import QueryResourceManager, TypeInfo, ChildResourceManager, ChildTypeInfo 

15 

16from c7n.filters.core import ValueFilter 

17from c7n.filters.offhours import OffHour, OnHour 

18 

19 

20@resources.register('instance') 

21class Instance(QueryResourceManager): 

22 

23 class resource_type(TypeInfo): 

24 service = 'compute' 

25 version = 'v1' 

26 component = 'instances' 

27 enum_spec = ('aggregatedList', 'items.*.instances[]', None) 

28 scope = 'project' 

29 name = id = 'name' 

30 labels = True 

31 default_report_fields = ['name', 'status', 'creationTimestamp', 'machineType', 'zone'] 

32 asset_type = "compute.googleapis.com/Instance" 

33 scc_type = "google.compute.Instance" 

34 metric_key = 'metric.labels.instance_name' 

35 urn_component = "instance" 

36 urn_zonal = True 

37 

38 @staticmethod 

39 def get(client, resource_info): 

40 # The api docs for compute instance get are wrong, 

41 # they spell instance as resourceId 

42 return client.execute_command( 

43 'get', {'project': resource_info['project_id'], 

44 'zone': resource_info['zone'], 

45 'instance': resource_info[ 

46 'resourceName'].rsplit('/', 1)[-1]}) 

47 

48 @staticmethod 

49 def get_label_params(resource, all_labels): 

50 project, zone, instance = re.match( 

51 '.*?/projects/(.*?)/zones/(.*?)/instances/(.*)', 

52 resource['selfLink']).groups() 

53 return {'project': project, 'zone': zone, 'instance': instance, 

54 'body': { 

55 'labels': all_labels, 

56 'labelFingerprint': resource['labelFingerprint'] 

57 }} 

58 

59 @classmethod 

60 def refresh(cls, client, resource): 

61 project, zone, name = re.match( 

62 '.*?/projects/(.*?)/zones/(.*?)/instances/(.*)', 

63 resource['selfLink']).groups() 

64 return cls.get( 

65 client, 

66 { 

67 'project_id': project, 

68 'zone': zone, 

69 'resourceName': name 

70 } 

71 ) 

72 

73 @classmethod 

74 def get_metric_resource_name(cls, resource, metric_key=None): 

75 key = metric_key or cls.metric_key 

76 if key == 'metric.labels.instance_name': 

77 return resource.get(cls.name) 

78 elif key == 'resource.labels.instance_id': 

79 return resource['id'] 

80 return resource.get(cls.name) 

81 

82 

83Instance.filter_registry.register('offhour', OffHour) 

84Instance.filter_registry.register('onhour', OnHour) 

85 

86 

87@Instance.filter_registry.register('effective-firewall') 

88class EffectiveFirewall(ValueFilter): 

89 """Filters instances by their effective firewall rules. 

90 See `getEffectiveFirewalls 

91 <https://cloud.google.com/compute/docs/reference/rest/v1/instances/getEffectiveFirewalls>`_ 

92 for valid fields. 

93 

94 :example: 

95 

96 Filter all instances that have a firewall rule that allows public 

97 acess 

98 

99 .. code-block:: yaml 

100 

101 policies: 

102 - name: find-publicly-accessable-instances 

103 resource: gcp.instance 

104 filters: 

105 - type: effective-firewall 

106 key: firewalls[*].sourceRanges[] 

107 op: contains 

108 value: "0.0.0.0/0" 

109 """ 

110 

111 schema = type_schema('effective-firewall', rinherit=ValueFilter.schema) 

112 permissions = ('compute.instances.getEffectiveFirewalls',) 

113 

114 def get_resource_params(self, resource): 

115 path_param_re = re.compile('.*?/projects/(.*?)/zones/(.*?)/instances/.*') 

116 project, zone = path_param_re.match(resource['selfLink']).groups() 

117 return {'project': project, 'zone': zone, 'instance': resource["name"]} 

118 

119 def process_resource(self, client, resource): 

120 params = self.get_resource_params(resource) 

121 effective_firewalls = [] 

122 for interface in resource["networkInterfaces"]: 

123 effective_firewalls.append(client.execute_command( 

124 'getEffectiveFirewalls', {"networkInterface": interface["name"], **params})) 

125 return super(EffectiveFirewall, self).process(effective_firewalls, None) 

126 

127 def get_client(self, session, model): 

128 return session.client( 

129 model.service, model.version, model.component) 

130 

131 def process(self, resources, event=None): 

132 model = self.manager.get_model() 

133 session = local_session(self.manager.session_factory) 

134 client = self.get_client(session, model) 

135 return [r for r in resources if self.process_resource(client, r)] 

136 

137 

138class InstanceAction(MethodAction): 

139 

140 def get_resource_params(self, model, resource): 

141 path_param_re = re.compile('.*?/projects/(.*?)/zones/(.*?)/instances/(.*)') 

142 project, zone, instance = path_param_re.match(resource['selfLink']).groups() 

143 return {'project': project, 'zone': zone, 'instance': instance} 

144 

145 

146@Instance.action_registry.register('start') 

147class Start(InstanceAction): 

148 

149 schema = type_schema('start') 

150 method_spec = {'op': 'start'} 

151 attr_filter = ('status', ('TERMINATED',)) 

152 

153 

154@Instance.action_registry.register('stop') 

155class Stop(InstanceAction): 

156 """Caution: `stop` in GCP is closer to terminate in terms of effect. 

157 

158 The `discard_local_ssd` specifies if local SSD should be discarded 

159 or not while stopping the instance. The default behavior from 

160 Google Cloud console is to keep the local SSD. Default 

161 `discard_local_ssd` is False. 

162 https://cloud.google.com/compute/docs/instances/stop-start-instance#stop-vm-local-ssd 

163 

164 `suspend` is closer to stop in other providers. 

165 

166 See https://cloud.google.com/compute/docs/instances/instance-life-cycle 

167 

168 """ 

169 

170 schema = type_schema('stop', discard_local_ssd={'type': 'boolean'}) 

171 method_spec = {'op': 'stop'} 

172 attr_filter = ('status', ('RUNNING',)) 

173 

174 def get_resource_params(self, model, resource): 

175 params = super().get_resource_params(model, resource) 

176 

177 # support stopping instance with local SSD, it requires to pass an additional param to 

178 # the stop request to discard local SSD (true/false) 

179 discard_local_ssd = self.data.get('discard_local_ssd', False) 

180 params['discardLocalSsd'] = discard_local_ssd 

181 

182 return params 

183 

184 

185@Instance.action_registry.register('suspend') 

186class Suspend(InstanceAction): 

187 

188 schema = type_schema('suspend') 

189 method_spec = {'op': 'suspend'} 

190 attr_filter = ('status', ('RUNNING',)) 

191 

192 

193@Instance.action_registry.register('resume') 

194class Resume(InstanceAction): 

195 

196 schema = type_schema('resume') 

197 method_spec = {'op': 'resume'} 

198 attr_filter = ('status', ('SUSPENDED',)) 

199 

200 

201@Instance.action_registry.register('delete') 

202class Delete(InstanceAction): 

203 

204 schema = type_schema('delete') 

205 method_spec = {'op': 'delete'} 

206 

207 

208@Instance.action_registry.register('detach-disks') 

209class DetachDisks(MethodAction): 

210 """ 

211 `Detaches <https://cloud.google.com/compute/docs/reference/rest/v1/instances/detachDisk>`_ 

212 all disks from instance. The action does not specify any parameters. 

213 

214 It may be useful to be used before deleting instances to not delete disks 

215 that are set to auto delete. 

216 

217 :Example: 

218 

219 .. code-block:: yaml 

220 

221 policies: 

222 - name: gcp-instance-detach-disks 

223 resource: gcp.instance 

224 filters: 

225 - type: value 

226 key: name 

227 value: instance-template-to-detahc 

228 actions: 

229 - type: detach-disks 

230 """ 

231 schema = type_schema('detach-disks') 

232 attr_filter = ('status', ('TERMINATED',)) 

233 method_spec = {'op': 'detachDisk'} 

234 path_param_re = re.compile( 

235 '.*?/projects/(.*?)/zones/(.*?)/instances/(.*)') 

236 

237 def validate(self): 

238 pass 

239 

240 def process_resource_set(self, client, model, resources): 

241 for resource in resources: 

242 self.process_resource(client, resource) 

243 

244 def process_resource(self, client, resource): 

245 op_name = 'detachDisk' 

246 

247 project, zone, instance = self.path_param_re.match( 

248 resource['selfLink']).groups() 

249 

250 base_params = {'project': project, 'zone': zone, 'instance': instance} 

251 for disk in resource.get('disks', []): 

252 params = dict(base_params, deviceName=disk['deviceName']) 

253 self.invoke_api(client, op_name, params) 

254 

255 

256@Instance.action_registry.register('create-machine-image') 

257class CreateMachineImage(MethodAction): 

258 """ 

259 `Creates <https://cloud.google.com/compute/docs/reference/rest/beta/machineImages/insert>`_ 

260 Machine Image from instance. 

261 

262 The `name_format` specifies name of image in python `format string <https://pyformat.info/>` 

263 

264 Inside format string there are defined variables: 

265 - `now`: current time 

266 - `instance`: whole instance resource 

267 

268 Default name format is `{instance[name]}` 

269 

270 :Example: 

271 

272 .. code-block:: yaml 

273 

274 policies: 

275 - name: gcp-create-machine-image 

276 resource: gcp.instance 

277 filters: 

278 - type: value 

279 key: name 

280 value: instance-create-to-make-image 

281 actions: 

282 - type: create-machine-image 

283 name_format: "{instance[name]:.50}-{now:%Y-%m-%d}" 

284 

285 """ 

286 schema = type_schema('create-machine-image', name_format={'type': 'string'}) 

287 method_spec = {'op': 'insert'} 

288 permissions = ('compute.machineImages.create',) 

289 

290 def get_resource_params(self, model, resource): 

291 path_param_re = re.compile('.*?/projects/(.*?)/zones/(.*?)/instances/(.*)') 

292 project, _, _ = path_param_re.match(resource['selfLink']).groups() 

293 name_format = self.data.get('name_format', '{instance[name]}') 

294 name = name_format.format(instance=resource, now=datetime.now()) 

295 

296 return {'project': project, 'sourceInstance': resource['selfLink'], 'body': {'name': name}} 

297 

298 def get_client(self, session, model): 

299 return session.client(model.service, "beta", "machineImages") 

300 

301 

302@resources.register('image') 

303class Image(QueryResourceManager): 

304 

305 class resource_type(TypeInfo): 

306 service = 'compute' 

307 version = 'v1' 

308 component = 'images' 

309 name = id = 'name' 

310 default_report_fields = [ 

311 "name", "description", "sourceType", "status", "creationTimestamp", 

312 "diskSizeGb", "family"] 

313 asset_type = "compute.googleapis.com/Image" 

314 urn_component = "image" 

315 labels = True 

316 

317 @staticmethod 

318 def get(client, resource_info): 

319 return client.execute_command( 

320 'get', {'project': resource_info['project_id'], 

321 'image': resource_info['image_id']}) 

322 

323 @staticmethod 

324 def get_label_params(resource, all_labels): 

325 project, resource_id = re.match( 

326 '.*?/projects/(.*?)/global/images/(.*)', 

327 resource['selfLink']).groups() 

328 return {'project': project, 'resource': resource_id, 

329 'body': { 

330 'labels': all_labels, 

331 'labelFingerprint': resource['labelFingerprint'] 

332 }} 

333 

334 @classmethod 

335 def refresh(cls, client, resource): 

336 project, resource_id = re.match( 

337 '.*?/projects/(.*?)/global/images/(.*)', 

338 resource['selfLink']).groups() 

339 return cls.get( 

340 client, 

341 { 

342 'project_id': project, 

343 'image_id': resource_id 

344 } 

345 ) 

346 

347 

348@Image.filter_registry.register('iam-policy') 

349class ImageIamPolicyFilter(IamPolicyFilter): 

350 """ 

351 Overrides the base implementation to process images resources correctly. 

352 """ 

353 permissions = ('compute.images.getIamPolicy',) 

354 

355 def _verb_arguments(self, resource): 

356 project, _ = re.match( 

357 '.*?/projects/(.*?)/global/images/(.*)', 

358 resource['selfLink']).groups() 

359 verb_arguments = {'resource': resource[self.manager.resource_type.id], 'project': project} 

360 return verb_arguments 

361 

362 def process_resources(self, resources): 

363 value_filter = IamPolicyValueFilter(self.data['doc'], self.manager) 

364 value_filter._verb_arguments = self._verb_arguments 

365 return value_filter.process(resources) 

366 

367 

368@Image.action_registry.register('delete') 

369class DeleteImage(MethodAction): 

370 

371 schema = type_schema('delete') 

372 method_spec = {'op': 'delete'} 

373 attr_filter = ('status', ('READY')) 

374 path_param_re = re.compile('.*?/projects/(.*?)/global/images/(.*)') 

375 

376 def get_resource_params(self, m, r): 

377 project, image_id = self.path_param_re.match(r['selfLink']).groups() 

378 return {'project': project, 'image': image_id} 

379 

380 

381@resources.register('disk') 

382class Disk(QueryResourceManager): 

383 

384 class resource_type(TypeInfo): 

385 service = 'compute' 

386 version = 'v1' 

387 component = 'disks' 

388 scope = 'zone' 

389 enum_spec = ('aggregatedList', 'items.*.disks[]', None) 

390 name = id = 'name' 

391 labels = True 

392 default_report_fields = ["name", "sizeGb", "status", "zone"] 

393 asset_type = "compute.googleapis.com/Disk" 

394 urn_component = "disk" 

395 urn_zonal = True 

396 

397 @staticmethod 

398 def get(client, resource_info): 

399 return client.execute_command( 

400 'get', {'project': resource_info['project_id'], 

401 'zone': resource_info['zone'], 

402 'disk': resource_info['disk_id']}) 

403 

404 @staticmethod 

405 def get_label_params(resource, all_labels): 

406 path_param_re = re.compile('.*?/projects/(.*?)/zones/(.*?)/disks/(.*)') 

407 project, zone, instance = path_param_re.match( 

408 resource['selfLink']).groups() 

409 return {'project': project, 'zone': zone, 'resource': instance, 

410 'body': { 

411 'labels': all_labels, 

412 'labelFingerprint': resource['labelFingerprint'] 

413 }} 

414 

415 

416@Disk.action_registry.register('snapshot') 

417class DiskSnapshot(MethodAction): 

418 """ 

419 `Snapshots <https://cloud.google.com/compute/docs/reference/rest/v1/disks/createSnapshot>`_ 

420 disk. 

421 

422 The `name_format` specifies name of snapshot in python `format string <https://pyformat.info/>` 

423 

424 Inside format string there are defined variables: 

425 - `now`: current time 

426 - `disk`: whole disk resource 

427 

428 Default name format is `{disk.name}` 

429 

430 :Example: 

431 

432 .. code-block:: yaml 

433 

434 policies: 

435 - name: gcp-disk-snapshot 

436 resource: gcp.disk 

437 filters: 

438 - type: value 

439 key: name 

440 value: disk-7 

441 actions: 

442 - type: snapshot 

443 name_format: "{disk[name]:.50}-{now:%Y-%m-%d}" 

444 """ 

445 schema = type_schema('snapshot', name_format={'type': 'string'}) 

446 method_spec = {'op': 'createSnapshot'} 

447 path_param_re = re.compile( 

448 '.*?/projects/(.*?)/zones/(.*?)/disks/(.*)') 

449 attr_filter = ('status', ('RUNNING', 'READY')) 

450 

451 def get_resource_params(self, model, resource): 

452 project, zone, resourceId = self.path_param_re.match(resource['selfLink']).groups() 

453 name_format = self.data.get('name_format', '{disk[name]}') 

454 name = name_format.format(disk=resource, now=datetime.now()) 

455 

456 return { 

457 'project': project, 

458 'zone': zone, 

459 'disk': resourceId, 

460 'body': { 

461 'name': name, 

462 'labels': resource.get('labels', {}), 

463 } 

464 } 

465 

466 

467@Disk.action_registry.register('delete') 

468class DiskDelete(MethodAction): 

469 

470 schema = type_schema('delete') 

471 method_spec = {'op': 'delete'} 

472 path_param_re = re.compile( 

473 '.*?/projects/(.*?)/zones/(.*?)/disks/(.*)') 

474 attr_filter = ('status', ('RUNNING', 'READY')) 

475 

476 def get_resource_params(self, m, r): 

477 project, zone, resourceId = self.path_param_re.match(r['selfLink']).groups() 

478 return { 

479 'project': project, 

480 'zone': zone, 

481 'disk': resourceId, 

482 } 

483 

484 

485@resources.register('snapshot') 

486class Snapshot(QueryResourceManager): 

487 

488 class resource_type(TypeInfo): 

489 service = 'compute' 

490 version = 'v1' 

491 component = 'snapshots' 

492 enum_spec = ('list', 'items[]', None) 

493 name = id = 'name' 

494 default_report_fields = ["name", "status", "diskSizeGb", "creationTimestamp"] 

495 asset_type = "compute.googleapis.com/Snapshot" 

496 urn_component = "snapshot" 

497 

498 @staticmethod 

499 def get(client, resource_info): 

500 return client.execute_command( 

501 'get', {'project': resource_info['project_id'], 

502 'snapshot': resource_info['snapshot_id']}) 

503 

504 

505@Snapshot.action_registry.register('delete') 

506class DeleteSnapshot(MethodAction): 

507 

508 schema = type_schema('delete') 

509 method_spec = {'op': 'delete'} 

510 attr_filter = ('status', ('READY', 'UPLOADING')) 

511 path_param_re = re.compile('.*?/projects/(.*?)/global/snapshots/(.*)') 

512 

513 def get_resource_params(self, m, r): 

514 project, snapshot_id = self.path_param_re.match(r['selfLink']).groups() 

515 # Docs are wrong :-( 

516 # https://cloud.google.com/compute/docs/reference/rest/v1/snapshots/delete 

517 return {'project': project, 'snapshot': snapshot_id} 

518 

519 

520@resources.register('instance-template') 

521class InstanceTemplate(QueryResourceManager): 

522 """GCP resource: https://cloud.google.com/compute/docs/reference/rest/v1/instanceTemplates""" 

523 class resource_type(TypeInfo): 

524 service = 'compute' 

525 version = 'v1' 

526 component = 'instanceTemplates' 

527 scope = 'zone' 

528 enum_spec = ('list', 'items[]', None) 

529 name = id = 'name' 

530 default_report_fields = [ 

531 name, "description", "creationTimestamp", 

532 "properties.machineType", "properties.description"] 

533 asset_type = "compute.googleapis.com/InstanceTemplate" 

534 urn_component = "instance-template" 

535 

536 @staticmethod 

537 def get(client, resource_info): 

538 return client.execute_command( 

539 'get', {'project': resource_info['project_id'], 

540 'instanceTemplate': resource_info['instance_template_name']}) 

541 

542 

543@InstanceTemplate.action_registry.register('delete') 

544class InstanceTemplateDelete(MethodAction): 

545 """ 

546 `Deletes <https://cloud.google.com/compute/docs/reference/rest/v1/instanceTemplates/delete>`_ 

547 an Instance Template. The action does not specify any parameters. 

548 

549 :Example: 

550 

551 .. code-block:: yaml 

552 

553 policies: 

554 - name: gcp-instance-template-delete 

555 resource: gcp.instance-template 

556 filters: 

557 - type: value 

558 key: name 

559 value: instance-template-to-delete 

560 actions: 

561 - type: delete 

562 """ 

563 schema = type_schema('delete') 

564 method_spec = {'op': 'delete'} 

565 

566 def get_resource_params(self, m, r): 

567 project, instance_template = re.match('.*/projects/(.*?)/.*/instanceTemplates/(.*)', 

568 r['selfLink']).groups() 

569 return {'project': project, 

570 'instanceTemplate': instance_template} 

571 

572 

573@resources.register('autoscaler') 

574class Autoscaler(QueryResourceManager): 

575 """GCP resource: https://cloud.google.com/compute/docs/reference/rest/v1/autoscalers""" 

576 class resource_type(TypeInfo): 

577 service = 'compute' 

578 version = 'v1' 

579 component = 'autoscalers' 

580 name = id = 'name' 

581 enum_spec = ('aggregatedList', 'items.*.autoscalers[]', None) 

582 default_report_fields = [ 

583 "name", "description", "status", "target", "recommendedSize"] 

584 asset_type = "compute.googleapis.com/Autoscaler" 

585 metric_key = "resource.labels.autoscaler_name" 

586 urn_component = "autoscaler" 

587 urn_zonal = True 

588 

589 @staticmethod 

590 def get(client, resource_info): 

591 project, zone, autoscaler = re.match( 

592 'projects/(.*?)/zones/(.*?)/autoscalers/(.*)', 

593 resource_info['resourceName']).groups() 

594 

595 return client.execute_command( 

596 'get', {'project': project, 

597 'zone': zone, 

598 'autoscaler': autoscaler}) 

599 

600 

601@Autoscaler.action_registry.register('set') 

602class AutoscalerSet(MethodAction): 

603 """ 

604 `Patches <https://cloud.google.com/compute/docs/reference/rest/v1/autoscalers/patch>`_ 

605 configuration parameters for the autoscaling algorithm. 

606 

607 The `coolDownPeriodSec` specifies the number of seconds that the autoscaler 

608 should wait before it starts collecting information from a new instance. 

609 

610 The `cpuUtilization.utilizationTarget` specifies the target CPU utilization that the 

611 autoscaler should maintain. 

612 

613 The `loadBalancingUtilization.utilizationTarget` specifies fraction of backend capacity 

614 utilization (set in HTTP(S) load balancing configuration) that autoscaler should maintain. 

615 

616 The `minNumReplicas` specifies the minimum number of replicas that the autoscaler can 

617 scale down to. 

618 

619 The `maxNumReplicas` specifies the maximum number of instances that the autoscaler can 

620 scale up to. 

621 

622 :Example: 

623 

624 .. code-block:: yaml 

625 

626 policies: 

627 - name: gcp-autoscaler-set 

628 resource: gcp.autoscaler 

629 filters: 

630 - type: value 

631 key: name 

632 value: instance-group-2 

633 actions: 

634 - type: set 

635 coolDownPeriodSec: 20 

636 cpuUtilization: 

637 utilizationTarget: 0.7 

638 loadBalancingUtilization: 

639 utilizationTarget: 0.7 

640 minNumReplicas: 1 

641 maxNumReplicas: 4 

642 """ 

643 schema = type_schema('set', 

644 **{ 

645 'coolDownPeriodSec': { 

646 'type': 'integer', 

647 'minimum': 15 

648 }, 

649 'cpuUtilization': { 

650 'type': 'object', 

651 'required': ['utilizationTarget'], 

652 'properties': { 

653 'utilizationTarget': { 

654 'type': 'number', 

655 'exclusiveMinimum': 0, 

656 'maximum': 1 

657 } 

658 }, 

659 }, 

660 'loadBalancingUtilization': { 

661 'type': 'object', 

662 'required': ['utilizationTarget'], 

663 'properties': { 

664 'utilizationTarget': { 

665 'type': 'number', 

666 'exclusiveMinimum': 0, 

667 'maximum': 1 

668 } 

669 } 

670 }, 

671 'maxNumReplicas': { 

672 'type': 'integer', 

673 'exclusiveMinimum': 0 

674 }, 

675 'minNumReplicas': { 

676 'type': 'integer', 

677 'exclusiveMinimum': 0 

678 } 

679 }) 

680 method_spec = {'op': 'patch'} 

681 path_param_re = re.compile('.*?/projects/(.*?)/zones/(.*?)/autoscalers/(.*)') 

682 method_perm = 'update' 

683 

684 def get_resource_params(self, model, resource): 

685 project, zone, autoscaler = self.path_param_re.match(resource['selfLink']).groups() 

686 body = {} 

687 

688 if 'coolDownPeriodSec' in self.data: 

689 body['coolDownPeriodSec'] = self.data['coolDownPeriodSec'] 

690 

691 if 'cpuUtilization' in self.data: 

692 body['cpuUtilization'] = self.data['cpuUtilization'] 

693 

694 if 'loadBalancingUtilization' in self.data: 

695 body['loadBalancingUtilization'] = self.data['loadBalancingUtilization'] 

696 

697 if 'maxNumReplicas' in self.data: 

698 body['maxNumReplicas'] = self.data['maxNumReplicas'] 

699 

700 if 'minNumReplicas' in self.data: 

701 body['minNumReplicas'] = self.data['minNumReplicas'] 

702 

703 result = {'project': project, 

704 'zone': zone, 

705 'autoscaler': autoscaler, 

706 'body': { 

707 'autoscalingPolicy': body 

708 }} 

709 

710 return result 

711 

712 

713@resources.register('zone') 

714class Zone(QueryResourceManager): 

715 """GC resource: https://cloud.google.com/compute/docs/reference/rest/v1/zones""" 

716 class resource_type(TypeInfo): 

717 service = 'compute' 

718 version = 'v1' 

719 component = 'zones' 

720 enum_spec = ('list', 'items[]', None) 

721 scope = 'project' 

722 name = id = 'name' 

723 default_report_fields = ['id', 'name', 'dnsName', 'creationTime', 'visibility'] 

724 asset_type = "compute.googleapis.com/compute" 

725 scc_type = "google.cloud.dns.ManagedZone" 

726 

727 

728@resources.register('compute-project') 

729class Project(QueryResourceManager): 

730 """GCP resource: https://cloud.google.com/compute/docs/reference/rest/v1/projects""" 

731 class resource_type(TypeInfo): 

732 service = 'compute' 

733 version = 'v1' 

734 component = 'projects' 

735 enum_spec = ('get', '[@]', None) 

736 name = id = 'name' 

737 default_report_fields = ["name"] 

738 asset_type = 'compute.googleapis.com/Project' 

739 

740 @staticmethod 

741 def get(client, resource_info): 

742 return client.execute_command( 

743 'get', {'project': resource_info['project_id']}) 

744 

745 

746@resources.register('instance-group-manager') 

747class InstanceGroupManager(ChildResourceManager): 

748 

749 class resource_type(ChildTypeInfo): 

750 service = 'compute' 

751 version = 'v1' 

752 component = 'instanceGroupManagers' 

753 enum_spec = ('list', 'items[]', None) 

754 name = id = 'name' 

755 parent_spec = { 

756 'resource': 'zone', 

757 'child_enum_params': { 

758 ('name', 'zone')}, 

759 'use_child_query': False, 

760 } 

761 default_report_fields = ['id', 'name', 'dnsName', 'creationTime', 'visibility']