def _parse_extensions()

in azurelinuxagent/common/protocol/extensions_goal_state_from_vm_settings.py [0:0]


    def _parse_extensions(self, vm_settings):
        # Sample (NOTE: The first sample is single-config, the second multi-config):
        # {
        #     ...
        #     "extensionGoalStates": [
        #         {
        #             "name": "Microsoft.Azure.Monitor.AzureMonitorLinuxAgent",
        #             "version": "1.9.1",
        #             "location": "https://zrdfepirv2cbn04prdstr01a.blob.core.windows.net/a47f0806d764480a8d989d009c75007d/Microsoft.Azure.Monitor_AzureMonitorLinuxAgent_useast2euap_manifest.xml",
        #             "state": "enabled",
        #             "autoUpgrade": true,
        #             "runAsStartupTask": false,
        #             "isJson": true,
        #             "useExactVersion": true,
        #             "encodedSignature": "MIIn...",
        #             "settingsSeqNo": 0,
        #             "settings": [
        #                 {
        #                     "protectedSettingsCertThumbprint": "BD447EF71C3ADDF7C837E84D630F3FAC22CCD22F",
        #                     "protectedSettings": "MIIBsAYJKoZIhvcNAQcDoIIBoTCCAZ0CAQAxggFpMIIBZQIBADBNMDkxNzA1BgoJkiaJk/IsZAEZFidXaW5kb3dzIEF6dXJlIENSUCBDZXJ0aWZpY2F0ZSBHZW5lcmF0b3ICEFpB/HKM/7evRk+DBz754wUwDQYJKoZIhvcNAQEBBQAEggEADPJwniDeIUXzxNrZCloitFdscQ59Bz1dj9DLBREAiM8jmxM0LLicTJDUv272Qm/4ZQgdqpFYBFjGab/9MX+Ih2x47FkVY1woBkckMaC/QOFv84gbboeQCmJYZC/rZJdh8rCMS+CEPq3uH1PVrvtSdZ9uxnaJ+E4exTPPviIiLIPtqWafNlzdbBt8HZjYaVw+SSe+CGzD2pAQeNttq3Rt/6NjCzrjG8ufKwvRoqnrInMs4x6nnN5/xvobKIBSv4/726usfk8Ug+9Q6Benvfpmre2+1M5PnGTfq78cO3o6mI3cPoBUjp5M0iJjAMGeMt81tyHkimZrEZm6pLa4NQMOEjArBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECC5nVaiJaWt+gAhgeYvxUOYHXw==",
        #                     "publicSettings": "{\"GCS_AUTO_CONFIG\":true}"
        #                 }
        #             ],
        #             "dependsOn": [
        #                 ...
        #             ]
        #         },
        #         {
        #             "name": "Microsoft.CPlat.Core.RunCommandHandlerLinux",
        #             "version": "1.2.0",
        #             "location": "https://umsavbvncrpzbnxmxzmr.blob.core.windows.net/f4086d41-69f9-3103-78e0-8a2c7e789d0f/f4086d41-69f9-3103-78e0-8a2c7e789d0f_manifest.xml",
        #             "failoverlocation": "https://umsajbjtqrb3zqjvgb2z.blob.core.windows.net/f4086d41-69f9-3103-78e0-8a2c7e789d0f/f4086d41-69f9-3103-78e0-8a2c7e789d0f_manifest.xml",
        #             "additionalLocations": [
        #                 "https://umsawqtlsshtn5v2nfgh.blob.core.windows.net/f4086d41-69f9-3103-78e0-8a2c7e789d0f/f4086d41-69f9-3103-78e0-8a2c7e789d0f_manifest.xml"
        #             ],
        #             "state": "enabled",
        #             "autoUpgrade": true,
        #             "runAsStartupTask": false,
        #             "isJson": true,
        #             "useExactVersion": true,
        #             "settingsSeqNo": 0,
        #             "isMultiConfig": true,
        #             "settings": [
        #                 {
        #                     "publicSettings": "{\"source\":{\"script\":\"echo '4abb1e88-f349-41f8-8442-247d9fdfcac5'\"}}",
        #                     "seqNo": 0,
        #                     "extensionName": "MCExt1",
        #                     "extensionState": "enabled"
        #                 },
        #                 {
        #                     "publicSettings": "{\"source\":{\"script\":\"echo 'e865c9bc-a7b3-42c6-9a79-cfa98a1ee8b3'\"}}",
        #                     "seqNo": 0,
        #                     "extensionName": "MCExt2",
        #                     "extensionState": "enabled"
        #                 },
        #                 {
        #                     "publicSettings": "{\"source\":{\"script\":\"echo 'f923e416-0340-485c-9243-8b84fb9930c6'\"}}",
        #                     "seqNo": 0,
        #                     "extensionName": "MCExt3",
        #                     "extensionState": "enabled"
        #                 }
        #             ],
        #             "dependsOn": [
        #                 ...
        #            ]
        #         }
        #         ...
        #     ]
        #     ...
        # }
        extension_goal_states = vm_settings.get("extensionGoalStates")
        if extension_goal_states is not None:
            if not isinstance(extension_goal_states, list):
                raise Exception("extension_goal_states should be an array (got {0})".format(type(extension_goal_states)))  # report only the type, since the value may contain secrets
            for extension_gs in extension_goal_states:
                extension = Extension()

                extension.name = extension_gs['name']
                extension.version = extension_gs['version']
                extension.state = extension_gs['state']
                # extension.encoded_signature should be None if 'encodedSignature' key does not exist for the extension
                extension.encoded_signature = extension_gs.get('encodedSignature')
                if extension.state not in ExtensionRequestedState.All:
                    raise Exception('Invalid extension state: {0} ({1})'.format(extension.state, extension.name))
                is_multi_config = extension_gs.get('isMultiConfig')
                if is_multi_config is not None:
                    extension.supports_multi_config = is_multi_config
                location = extension_gs.get('location')
                if location is not None:
                    extension.manifest_uris.append(location)
                fail_over_location = extension_gs.get('failoverLocation')
                if fail_over_location is not None:
                    extension.manifest_uris.append(fail_over_location)
                additional_locations = extension_gs.get('additionalLocations')
                if additional_locations is not None:
                    if not isinstance(additional_locations, list):
                        raise Exception('additionalLocations should be an array (got {0})'.format(additional_locations))
                    extension.manifest_uris.extend(additional_locations)

                #
                # Settings
                #
                settings_list = extension_gs.get('settings')
                if settings_list is not None:
                    if not isinstance(settings_list, list):
                        raise Exception("'settings' should be an array (extension: {0})".format(extension.name))
                    if not extension.supports_multi_config and len(settings_list) > 1:
                        raise Exception("Single-config extension includes multiple settings (extension: {0})".format(extension.name))

                    for s in settings_list:
                        settings = ExtensionSettings()
                        public_settings = s.get('publicSettings')
                        # Note that publicSettings, protectedSettings and protectedSettingsCertThumbprint can be None; do not change this to, for example,
                        # empty, since those values are serialized to the extension's status file and extensions may depend on the current implementation
                        # (for example, no public settings would currently be serialized as '"publicSettings": null')
                        settings.publicSettings = None if public_settings is None else json.loads(public_settings)
                        settings.protectedSettings = s.get('protectedSettings')
                        thumbprint = s.get('protectedSettingsCertThumbprint')
                        if thumbprint is None and settings.protectedSettings is not None:
                            raise Exception("The certificate thumbprint for protected settings is missing (extension: {0})".format(extension.name))
                        settings.certificateThumbprint = thumbprint

                        # in multi-config each settings have their own name, sequence number and state
                        if extension.supports_multi_config:
                            settings.name = s['extensionName']
                            settings.sequenceNumber = s['seqNo']
                            settings.state = s['extensionState']
                        else:
                            settings.name = extension.name
                            settings.sequenceNumber = extension_gs['settingsSeqNo']
                            settings.state = extension.state
                        extension.settings.append(settings)

                #
                # Dependency level
                #
                depends_on = extension_gs.get("dependsOn")
                if depends_on is not None:
                    self._parse_dependency_level(depends_on, extension)

                self._extensions.append(extension)