@f5devcentral/f5-cloud-libs-azure
Advanced tools
Comparing version 2.0.2 to 2.2.0
@@ -16,6 +16,8 @@ /** | ||
*/ | ||
'use strict'; | ||
/* eslint-disable global-require */ | ||
module.exports = { | ||
provider: require("./lib/azureAutoscaleProvider.js") | ||
}; | ||
provider: require('./lib/azureAutoscaleProvider.js') | ||
}; |
{ | ||
"name": "@f5devcentral/f5-cloud-libs-azure", | ||
"version": "2.0.2", | ||
"version": "2.2.0", | ||
"description": "Azure implementation of f5-cloud-libs cloud provider code", | ||
@@ -32,3 +32,3 @@ "keywords": [ | ||
"peerDependencies": { | ||
"@f5devcentral/f5-cloud-libs": "^4.0.0-beta.6" | ||
"@f5devcentral/f5-cloud-libs": "^4.2.0-beta.1" | ||
}, | ||
@@ -42,3 +42,3 @@ "devDependencies": { | ||
"scripts": { | ||
"lint": "node node_modules/eslint/bin/eslint lib", | ||
"lint": "node node_modules/eslint/bin/eslint lib scripts", | ||
"package": "./package.sh", | ||
@@ -45,0 +45,0 @@ "test": "node node_modules/nodeunit/bin/nodeunit --reporter eclipse test test/lib", |
@@ -11,2 +11,3 @@ #!/usr/bin/env node | ||
const azureStorage = require('azure-storage'); | ||
const azureEnvironment = require('ms-rest-azure/lib/azureEnvironment'); | ||
const f5CloudLibs = require('@f5devcentral/f5-cloud-libs'); | ||
@@ -47,2 +48,25 @@ | ||
const tenantId = credentialsFile.tenantId; | ||
let location = credentialsFile.location; | ||
uniqueLabel = credentialsFile.uniqueLabel; | ||
resourceGroup = credentialsFile.resourceGroupName; | ||
// Detect environment based on location (region), default to Azure | ||
let environment = azureEnvironment.Azure; | ||
if (location) { | ||
location = location.toLowerCase(); | ||
logger.silly(`Location: ${location}`); | ||
// Azure US Government cloud regions: US DoD Central, US DoD East, US Gov Arizona, | ||
// US Gov Iowa, US Gov Non-Regional, US Gov Texas, US Gov Virginia, US Sec East1, US Sec Wes | ||
if (location.includes('usgov') || location.includes('usdod') || location.includes('ussec')) { | ||
environment = azureEnvironment.AzureUSGovernment; | ||
// Azure China cloud regions: China East, China North | ||
} else if (location.includes('china')) { | ||
environment = azureEnvironment.AzureChina; | ||
// Azure Germany cloud regions: Germany Central, Germany Non-Regional, Germany Northeast | ||
// Note: There is Azure commercial cloud regions in germany so have to be specific | ||
} else if (location.includes('germanycentral') || location.includes('germanynortheast') || | ||
location.includes('germanynonregional')) { | ||
environment = azureEnvironment.AzureGermanCloud; | ||
} | ||
} | ||
storageAccount = credentialsFile.storageAccount; | ||
@@ -52,8 +76,13 @@ storageKey = credentialsFile.storageKey; | ||
storageAccount, | ||
storageKey | ||
storageKey, | ||
`${storageAccount}.blob${environment.storageEndpointSuffix}` | ||
); | ||
const credentials = new msRestAzure.ApplicationTokenCredentials(clientId, tenantId, secret); | ||
uniqueLabel = credentialsFile.uniqueLabel; | ||
resourceGroup = credentialsFile.resourceGroupName; | ||
networkClient = new NetworkManagementClient(credentials, subscriptionId); | ||
const credentials = new msRestAzure.ApplicationTokenCredentials( | ||
clientId, tenantId, secret, { environment } | ||
); | ||
networkClient = new NetworkManagementClient( | ||
credentials, | ||
subscriptionId, | ||
environment.resourceManagerEndpointUrl | ||
); | ||
} else { | ||
@@ -89,3 +118,6 @@ logger.error('Credentials file not found'); | ||
desiredConfiguration: { | ||
nicArr: {} | ||
nicArr: { | ||
disassociateArr: [], | ||
associateArr: [] | ||
} | ||
} | ||
@@ -172,3 +204,3 @@ }; | ||
logger.debug('Failover database status:', failoverDbBlob.status); | ||
if (results.status === FAILOVER_STATUS_RUN || results.status === FAILOVER_STATUS_FAIL) { | ||
if (failoverDbBlob.status === FAILOVER_STATUS_RUN || failoverDbBlob.status === FAILOVER_STATUS_FAIL) { | ||
if (typeof failoverDbBlob.timeStamp !== 'undefined' && failoverDbBlob.timeStamp !== '') { | ||
@@ -482,3 +514,2 @@ const differenceInMs = new Date() - Date.parse(failoverDbBlob.timeStamp); | ||
let t; | ||
let address; | ||
const entries = tgs.entries; | ||
@@ -496,3 +527,2 @@ const hostname = global.hostname; | ||
let theirIpForwarding; | ||
let virtualAddressTrafficGroup; | ||
@@ -504,2 +534,3 @@ let associateArr = []; | ||
const mySelfIpArr = []; | ||
const floatingSelfIpArr = []; | ||
const myTrafficGroupsArr = []; | ||
@@ -543,8 +574,2 @@ let theirNicArr = []; | ||
selfIps.forEach((self) => { | ||
mySelfIpArr.push({ | ||
address: self.address.split('/')[0] | ||
}); | ||
}); | ||
Object.keys(entries).forEach((key) => { | ||
@@ -559,2 +584,22 @@ if (entries[key].nestedStats.entries.deviceName.description.includes(hostname) | ||
selfIps.forEach((self) => { | ||
let tgMatch = false; | ||
myTrafficGroupsArr.forEach((tgmember) => { | ||
if (tgmember.trafficGroup.includes(self.trafficGroup)) { | ||
tgMatch = true; | ||
} | ||
}); | ||
if (tgMatch) { | ||
floatingSelfIpArr.push({ | ||
address: self.address.split('/')[0], | ||
trafficGroup: self.trafficGroup | ||
}); | ||
} else { | ||
mySelfIpArr.push({ | ||
address: self.address.split('/')[0] | ||
}); | ||
} | ||
}); | ||
if (!vs.length) { | ||
@@ -564,7 +609,7 @@ logger.error('No virtual addresses exist, create them prior to failover.'); | ||
vs.forEach((virtualAddress) => { | ||
address = virtualAddress.address; | ||
virtualAddressTrafficGroup = virtualAddress.trafficGroup; | ||
const address = virtualAddress.address; | ||
const tg = virtualAddress.trafficGroup; | ||
myTrafficGroupsArr.forEach((tgmember) => { | ||
if (tgmember.trafficGroup.includes(virtualAddressTrafficGroup)) { | ||
if (tgmember.trafficGroup.includes(tg)) { | ||
trafficGroupIpArr.push({ | ||
@@ -578,2 +623,19 @@ address | ||
if (!floatingSelfIpArr.length) { | ||
logger.debug('No floating self IPs exist, just continue.'); | ||
} else { | ||
floatingSelfIpArr.forEach((floatingSelf) => { | ||
const address = floatingSelf.address; | ||
const tg = floatingSelf.trafficGroup; | ||
myTrafficGroupsArr.forEach((tgmember) => { | ||
if (tgmember.trafficGroup.includes(tg)) { | ||
trafficGroupIpArr.push({ | ||
address | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
nics.forEach((nic) => { | ||
@@ -638,3 +700,4 @@ if (nic.name.toLowerCase().includes(uniqueLabel.toLowerCase()) | ||
for (t = trafficGroupIpArr.length - 1; t >= 0; t--) { | ||
if (trafficGroupIpArr[t].address.includes(theirNicArr[i].privateIPAddress)) { | ||
if (trafficGroupIpArr[t].address === theirNicArr[i].privateIPAddress) { | ||
logger.silly('Match:', theirNicArr[i].privateIPAddress); | ||
myNicArr.push(getNicConfig(theirNicArr[i])); | ||
@@ -674,8 +737,10 @@ theirNicArr.splice(i, 1); | ||
// Replace current configuration with previous desired configuration from failover database | ||
disassociateArr = failoverDbBlob.desiredConfiguration.nicArr.disassociateArr; | ||
associateArr = failoverDbBlob.desiredConfiguration.nicArr.associateArr; | ||
if (failoverDbBlob.desiredConfiguration.nicArr.disassociateArr && | ||
failoverDbBlob.desiredConfiguration.nicArr.associateArr) { | ||
disassociateArr = failoverDbBlob.desiredConfiguration.nicArr.disassociateArr; | ||
associateArr = failoverDbBlob.desiredConfiguration.nicArr.associateArr; | ||
} | ||
} | ||
// Update failover database with desired configuration prior to updating NICs | ||
if (disassociateArr.length && associateArr.length) { | ||
failoverDbBlob.desiredConfiguration.nicArr = {}; | ||
if (disassociateArr && disassociateArr.length && associateArr && associateArr.length) { | ||
failoverDbBlob.desiredConfiguration.nicArr.disassociateArr = disassociateArr; | ||
@@ -682,0 +747,0 @@ failoverDbBlob.desiredConfiguration.nicArr.associateArr = associateArr; |
@@ -41,2 +41,3 @@ /** | ||
let utilMock; | ||
let localCryptoUtilMock; | ||
let AzureAutoscaleProvider; | ||
@@ -46,2 +47,6 @@ let provider; | ||
let receivedClientId; | ||
let receivedSecret; | ||
let receivedTenantId; | ||
// Our tests cause too many event listeners. Turn off the check. | ||
@@ -54,2 +59,3 @@ process.setMaxListeners(0); | ||
utilMock = require('@f5devcentral/f5-cloud-libs').util; | ||
localCryptoUtilMock = require('@f5devcentral/f5-cloud-libs').localCryptoUtil; | ||
azureMock = require('ms-rest-azure'); | ||
@@ -105,2 +111,5 @@ azureNetworkMock = require('azure-arm-network'); | ||
) { | ||
receivedClientId = aClientId; | ||
receivedSecret = aSecret; | ||
receivedTenantId = aTenantId; | ||
cb(null, { signRequest() {} }); | ||
@@ -119,18 +128,2 @@ }; | ||
let receivedClientId; | ||
let receivedSecret; | ||
let receivedTenantId; | ||
azureMock.loginWithServicePrincipalSecret = function loginWithServicePrincipalSecret( | ||
aClientId, | ||
aSecret, | ||
aTenantId, | ||
cb | ||
) { | ||
receivedClientId = clientId; | ||
receivedSecret = secret; | ||
receivedTenantId = tenantId; | ||
cb(null, { signRequest() {} }); | ||
}; | ||
provider.init(providerOptions) | ||
@@ -145,2 +138,28 @@ .then(() => { | ||
testAzureLoginSecretId(test) { | ||
const storedSecret = 'my secret from rest'; | ||
const providerOptions = { | ||
clientId, | ||
tenantId, | ||
subscriptionId, | ||
secretId: 'foo', | ||
scaleSet: 'myScaleSet', | ||
resourceGroup: 'myResourceGroup' | ||
}; | ||
localCryptoUtilMock.decryptDataFromRestStorage = function decryptDataFromRestStorage() { | ||
return q( | ||
{ | ||
servicePrincipalSecret: storedSecret | ||
} | ||
); | ||
}; | ||
provider.init(providerOptions) | ||
.then(() => { | ||
test.strictEqual(receivedSecret, storedSecret); | ||
test.done(); | ||
}); | ||
}, | ||
testAzureLoginBadCredentialsUrl(test) { | ||
@@ -412,33 +431,25 @@ const errorMessage = 'bad url'; | ||
testBasic(test) { | ||
test.expect(1); | ||
test.expect(19); | ||
provider.getInstances() | ||
.then((instances) => { | ||
test.deepEqual(instances, { | ||
123: { | ||
mgmtIp: '5.6.7.8', | ||
privateIp: '5.6.7.8', | ||
publicIp: '123.456.789.1', | ||
hostname: '5.6.7.8_myHostname', | ||
providerVisible: true, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
}, | ||
456: { | ||
mgmtIp: '7.8.9.0', | ||
privateIp: '7.8.9.0', | ||
publicIp: undefined, | ||
hostname: '7.8.9.0_myHostname', | ||
providerVisible: true, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
} | ||
}); | ||
test.strictEqual(instances['123'].mgmtIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].privateIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].publicIp, '123.456.789.1'); | ||
test.strictEqual(instances['123'].hostname, '5.6.7.8_myHostname'); | ||
test.strictEqual(instances['123'].providerVisible, true); | ||
test.strictEqual(instances['123'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['123'].isMaster, false); | ||
test.strictEqual(instances['123'].external, false); | ||
test.strictEqual(instances['123'].lastBackup, new Date(1970, 1, 1).getTime()); | ||
test.strictEqual(instances['123'].versionOk, true); | ||
test.strictEqual(instances['456'].mgmtIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].privateIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].hostname, '7.8.9.0_myHostname'); | ||
test.strictEqual(instances['456'].providerVisible, true); | ||
test.strictEqual(instances['456'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['456'].isMaster, false); | ||
test.strictEqual(instances['456'].external, false); | ||
test.strictEqual(instances['456'].lastBackup, new Date(1970, 1, 1).getTime()); | ||
test.strictEqual(instances['456'].versionOk, true); | ||
}) | ||
@@ -565,33 +576,23 @@ .catch((err) => { | ||
test.expect(1); | ||
test.expect(17); | ||
provider.getInstances() | ||
.then((instances) => { | ||
test.deepEqual(instances, { | ||
123: { | ||
mgmtIp: '5.6.7.8', | ||
privateIp: '5.6.7.8', | ||
publicIp: '123.456.789.1', | ||
hostname: '5.6.7.8_myHostname', | ||
providerVisible: false, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
}, | ||
456: { | ||
mgmtIp: '7.8.9.0', | ||
privateIp: '7.8.9.0', | ||
publicIp: undefined, | ||
hostname: '7.8.9.0_myHostname', | ||
providerVisible: true, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
} | ||
}); | ||
test.strictEqual(instances['123'].mgmtIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].privateIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].publicIp, '123.456.789.1'); | ||
test.strictEqual(instances['123'].hostname, '5.6.7.8_myHostname'); | ||
test.strictEqual(instances['123'].providerVisible, false); | ||
test.strictEqual(instances['123'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['123'].isMaster, false); | ||
test.strictEqual(instances['123'].external, false); | ||
test.strictEqual(instances['123'].versionOk, true); | ||
test.strictEqual(instances['456'].mgmtIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].privateIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].hostname, '7.8.9.0_myHostname'); | ||
test.strictEqual(instances['456'].providerVisible, true); | ||
test.strictEqual(instances['456'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['456'].isMaster, false); | ||
test.strictEqual(instances['456'].external, false); | ||
test.strictEqual(instances['456'].versionOk, true); | ||
}) | ||
@@ -645,33 +646,23 @@ .catch((err) => { | ||
test.expect(1); | ||
test.expect(17); | ||
provider.getInstances() | ||
.then((instances) => { | ||
test.deepEqual(instances, { | ||
123: { | ||
mgmtIp: '5.6.7.8', | ||
privateIp: '5.6.7.8', | ||
publicIp: '123.456.789.1', | ||
hostname: '5.6.7.8_myHostname', | ||
providerVisible: true, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
}, | ||
456: { | ||
mgmtIp: '7.8.9.0', | ||
privateIp: '7.8.9.0', | ||
publicIp: undefined, | ||
hostname: '7.8.9.0_myHostname', | ||
providerVisible: false, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
} | ||
}); | ||
test.strictEqual(instances['123'].mgmtIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].privateIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].publicIp, '123.456.789.1'); | ||
test.strictEqual(instances['123'].hostname, '5.6.7.8_myHostname'); | ||
test.strictEqual(instances['123'].providerVisible, true); | ||
test.strictEqual(instances['123'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['123'].isMaster, false); | ||
test.strictEqual(instances['123'].external, false); | ||
test.strictEqual(instances['123'].versionOk, true); | ||
test.strictEqual(instances['456'].mgmtIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].privateIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].hostname, '7.8.9.0_myHostname'); | ||
test.strictEqual(instances['456'].providerVisible, false); | ||
test.strictEqual(instances['456'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['456'].isMaster, false); | ||
test.strictEqual(instances['456'].external, false); | ||
test.strictEqual(instances['456'].versionOk, true); | ||
}) | ||
@@ -710,33 +701,23 @@ .catch((err) => { | ||
test.expect(1); | ||
test.expect(17); | ||
provider.getInstances() | ||
.then((instances) => { | ||
test.deepEqual(instances, { | ||
123: { | ||
mgmtIp: '5.6.7.8', | ||
privateIp: '5.6.7.8', | ||
publicIp: '123.456.789.1', | ||
hostname: '5.6.7.8_myHostname', | ||
providerVisible: true, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
}, | ||
456: { | ||
mgmtIp: '7.8.9.0', | ||
privateIp: '7.8.9.0', | ||
publicIp: undefined, | ||
hostname: '7.8.9.0_myHostname', | ||
providerVisible: true, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
} | ||
}); | ||
test.strictEqual(instances['123'].mgmtIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].privateIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].publicIp, '123.456.789.1'); | ||
test.strictEqual(instances['123'].hostname, '5.6.7.8_myHostname'); | ||
test.strictEqual(instances['123'].providerVisible, true); | ||
test.strictEqual(instances['123'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['123'].isMaster, false); | ||
test.strictEqual(instances['123'].external, false); | ||
test.strictEqual(instances['123'].versionOk, true); | ||
test.strictEqual(instances['456'].mgmtIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].privateIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].hostname, '7.8.9.0_myHostname'); | ||
test.strictEqual(instances['456'].providerVisible, true); | ||
test.strictEqual(instances['456'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['456'].isMaster, false); | ||
test.strictEqual(instances['456'].external, false); | ||
test.strictEqual(instances['456'].versionOk, true); | ||
}) | ||
@@ -809,40 +790,23 @@ .catch((err) => { | ||
test.expect(1); | ||
test.expect(17); | ||
provider.getInstances({ externalTag }) | ||
.then((instances) => { | ||
test.deepEqual(instances, { | ||
123: { | ||
mgmtIp: '5.6.7.8', | ||
privateIp: '5.6.7.8', | ||
publicIp: '123.456.789.1', | ||
hostname: '5.6.7.8_myHostname', | ||
providerVisible: true, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
}, | ||
456: { | ||
mgmtIp: '7.8.9.0', | ||
privateIp: '7.8.9.0', | ||
publicIp: undefined, | ||
hostname: '7.8.9.0_myHostname', | ||
providerVisible: true, | ||
status: AutoscaleInstance.INSTANCE_STATUS_OK, | ||
version: undefined, | ||
isMaster: false, | ||
external: false, | ||
lastBackup: new Date(1970, 1, 1).getTime(), | ||
versionOk: true | ||
}, | ||
'myResourceGroup-myInterface': { | ||
mgmtIp: '10.11.12.13', | ||
privateIp: '10.11.12.13', | ||
external: true, | ||
hostname: '10.11.12.13_myHostname', | ||
providerVisible: true | ||
} | ||
}); | ||
test.strictEqual(instances['123'].mgmtIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].privateIp, '5.6.7.8'); | ||
test.strictEqual(instances['123'].publicIp, '123.456.789.1'); | ||
test.strictEqual(instances['123'].hostname, '5.6.7.8_myHostname'); | ||
test.strictEqual(instances['123'].providerVisible, true); | ||
test.strictEqual(instances['123'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['123'].isMaster, false); | ||
test.strictEqual(instances['123'].external, false); | ||
test.strictEqual(instances['123'].versionOk, true); | ||
test.strictEqual(instances['456'].mgmtIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].privateIp, '7.8.9.0'); | ||
test.strictEqual(instances['456'].hostname, '7.8.9.0_myHostname'); | ||
test.strictEqual(instances['456'].providerVisible, true); | ||
test.strictEqual(instances['456'].status, AutoscaleInstance.INSTANCE_STATUS_OK); | ||
test.strictEqual(instances['456'].isMaster, false); | ||
test.strictEqual(instances['456'].external, false); | ||
test.strictEqual(instances['456'].versionOk, true); | ||
}) | ||
@@ -849,0 +813,0 @@ .catch((err) => { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
348404
14
8736