Skip to content

Commit

Permalink
fix: add commands for SCF Alias (#39)
Browse files Browse the repository at this point in the history
* feat: add commands for SCF Alias

* feat: add commands for SCF Alias

* fix: update the version of tencent-component-toolkit in package.json

* fix: check function status after call PublishVersion

Co-authored-by: p_kaiyuzeng <[email protected]>
  • Loading branch information
Jominja and p_kaiyuzeng authored Nov 2, 2020
1 parent b8d2de1 commit e939be3
Show file tree
Hide file tree
Showing 4 changed files with 294 additions and 3 deletions.
14 changes: 13 additions & 1 deletion serverless.component.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: scf
version: 0.1.8
version: 0.1.9
author: Tencent Cloud, Inc.
org: Tencent Cloud, Inc.
description: Deploy a serverless cloud function on Tencent Cloud.
Expand Down Expand Up @@ -235,3 +235,15 @@ actions:
type: string
remove:
definition: Remove your Express.js application
list_alias:
definition: Show your aliases
create_alias:
definition: Create alias for function
update_alias:
definition: Update alias for function
delete_alias:
definition: Delete alias for function
publish_ver:
definition: Publish a new version of function
invoke:
definition: Invoke function synchronously
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"dependencies": {
"download": "^8.0.0",
"tencent-component-toolkit": "^1.17.4",
"tencent-component-toolkit": "^1.18.2",
"type": "^2.0.0"
}
}
190 changes: 189 additions & 1 deletion src/serverless.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { Component } = require('@serverless/core')
const { Scf } = require('tencent-component-toolkit')
const { TypeError } = require('tencent-component-toolkit/src/utils/error')
const { prepareInputs, getType, getDefaultProtocol } = require('./utils')
const { prepareInputs, prepareAliasInputs, getType, getDefaultProtocol } = require('./utils')
const CONFIGS = require('./config')

class ServerlessComponent extends Component {
Expand Down Expand Up @@ -145,6 +145,194 @@ class ServerlessComponent extends Component {
this.state = {}
console.log(`Removed Tencent ${CONFIGS.compFullname}`)
}

async list_alias(inputs) {
try {
const credentials = this.getCredentials()
const region = inputs.region || CONFIGS.region

const alias_params = {}
alias_params.functionName = inputs.function
alias_params.functionVersion = inputs.version
alias_params.namesapce = inputs.namespace

console.log(`list alias for function ${inputs.function}...`)
const scf = new Scf(credentials, region)

const scfOutput = await scf.listAlias(alias_params)
console.log(`list alias for function ${inputs.function}...`)

const aliases = scfOutput.Aliases
const listAlias = {
alias: []
}

for (let i = 0; i < aliases.length; i++) {
const mainVersion = aliases[i].FunctionVersion
const addWeights = aliases[i].RoutingConfig.AdditionalVersionWeights[0] || { Weight: 0 }
const otherVersion = addWeights.Version || null
const otherWeight = Number(addWeights.Weight).toFixed(1) || 0
const mainWeight = (1 - otherWeight).toFixed(1)

const alias_unit = {}
alias_unit[aliases[i].Name] = {}
const weight = {}
weight[mainVersion] = mainWeight
if (otherVersion) {
weight[otherVersion] = otherWeight
}
alias_unit[aliases[i].Name].weight = JSON.stringify(weight)

listAlias.alias.push(alias_unit)
}
console.log(listAlias)
return listAlias
} catch (e) {
return {
requestId: e.reqId,
message: e.message
}
}
}

async create_alias(inputs) {
try {
const credentials = this.getCredentials()
const region = inputs.region || CONFIGS.region

const alias_params = prepareAliasInputs(inputs)

if (alias_params.isPramasError) {
return {
message: alias_params.message
}
}

console.log(`Creating alias for function ${inputs.function}...`)
const scf = new Scf(credentials, region)
await scf.createAlias(alias_params)
console.log(`Creating alias for function ${inputs.function}...`)

const aliasOutput = await scf.getAlias(alias_params)

return aliasOutput
} catch (e) {
return {
requestId: e.reqId,
message: e.message
}
}
}

async update_alias(inputs) {
try {
const credentials = this.getCredentials()
const region = inputs.region || CONFIGS.region

const alias_params = prepareAliasInputs(inputs)

if (alias_params.isPramasError) {
return {
ErrMsg: alias_params.message
}
}

console.log(`Updating alias for function ${inputs.function}...`)
const scf = new Scf(credentials, region)

await scf.updateAlias(alias_params)
console.log(`Updated alias for function ${inputs.function}...`)

const aliasOutput = await scf.getAlias(alias_params)

return aliasOutput
} catch (e) {
return {
requestId: e.reqId,
message: e.message
}
}
}

async delete_alias(inputs) {
try {
const credentials = this.getCredentials()
const region = inputs.region || CONFIGS.region

const alias_params = {}
alias_params.functionName = inputs.function
alias_params.aliasName = inputs.name
alias_params.namesapce = inputs.namespace

console.log(`delete alias for function ${inputs.function}...`)
const scf = new Scf(credentials, region)

const scfOutput = await scf.deleteAlias(alias_params)
console.log(`deleted alias for function ${inputs.function}...`)
return scfOutput
} catch (e) {
return {
requestId: e.reqId,
message: e.message
}
}
}

async publish_ver(inputs) {
try {
const credentials = this.getCredentials()
const region = inputs.region || CONFIGS.region

const publish_params = {}
publish_params.functionName = inputs.function
publish_params.namespace = inputs.namespace
publish_params.description = inputs.description

const scf = new Scf(credentials, region)

const scfOutput = await scf.publishVersion(publish_params)
console.log(`published version for function ${inputs.function}...`)

await scf.isOperationalStatus(scfOutput.Namespace, inputs.function, scfOutput.FunctionVersion)

this.state.lastVersion = scfOutput.FunctionVersion
await this.save()
scfOutput.lastVersion = scfOutput.FunctionVersion
delete scfOutput.FunctionVersion

return scfOutput
} catch (e) {
return {
requestId: e.reqId,
message: e.message
}
}
}

async invoke(inputs) {
try {
const credentials = this.getCredentials()
const region = inputs.region || CONFIGS.region

const invoke_params = {}
invoke_params.functionName = inputs.function
invoke_params.namespace = inputs.namespace
invoke_params.invocationType = 'RequestResponse'
invoke_params.clientContext = inputs.clientContext || {}

console.log(`invoke for function ${inputs.function}...`)
const scf = new Scf(credentials, region)

const scfOutput = await scf.invoke(invoke_params)
console.log(`invoke for function ${inputs.function}...`)
return scfOutput
} catch (e) {
return {
requestId: e.reqId,
message: e.message
}
}
}
}

module.exports = ServerlessComponent
91 changes: 91 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,101 @@ const prepareInputs = async (instance, credentials, appId, inputs) => {
}
}

const prepareAliasInputs = (inputs) => {
const outputs = {}

if (typeof inputs.name == 'undefined') {
outputs.isPramasError = true
outputs.message = 'The parameter "name" is missing'
return outputs
} else if (typeof inputs.name != 'string') {
outputs.isPramasError = true
outputs.message = 'The type of parameter "name" is string'
return outputs
}

if (typeof inputs.function == 'undefined') {
outputs.isPramasError = true
outputs.message = 'The parameter "function" is missing'
return outputs
} else if (typeof inputs.function != 'string') {
outputs.isPramasError = true
outputs.message = 'The type of parameter "function" is string'
return outputs
}

if (typeof inputs.version == 'undefined') {
outputs.isPramasError = true
outputs.message = 'The parameter "version" is missing'
return outputs
} else if (typeof inputs.version != 'number' && typeof inputs.version != 'string') {
outputs.isPramasError = true
outputs.message = 'The type of parameter "version" is number or string'
return outputs
}

if (!inputs.namespace) {
inputs.namespace = 'default'
} else if (typeof inputs.namespace != 'string') {
outputs.isPramasError = true
outputs.message = 'The type of parameter "namespace" is string'
return outputs
}

if (!inputs.description) {
inputs.description = ''
} else if (typeof inputs.description != 'string') {
outputs.isPramasError = true
outputs.message = 'The type of parameter "description" is string'
return outputs
}

if (typeof inputs.config == 'undefined') {
outputs.isPramasError = true
outputs.message = 'The parameter "config" is missing'
return outputs
} else if (typeof inputs.config != 'object') {
outputs.isPramasError = true
outputs.message =
'The parameter "config" is not illegal. The right format is like that:config=\'{"weights":{"2":0.1}}\''
return outputs
}

if (typeof inputs.config.weights != 'object') {
outputs.isPramasError = true
outputs.message =
'The parameter "config" is not illegal. The right format is like that:config=\'{"weights":{"2":0.1}}\''
return outputs
}

let lastVersion, traffic
try {
lastVersion = Object.keys(inputs.config.weights)[0]
traffic = Object.values(inputs.config.weights)[0]
} catch (e) {
outputs.isPramasError = true
outputs.message =
'The parameter "config" is not illegal. The right format is like that:config=\'{"weights":{"2":0.1}}\''
return outputs
}

outputs.isPramasError = false
outputs.aliasName = inputs.name
outputs.functionName = inputs.function
outputs.namespace = inputs.namespace
outputs.functionVersion = inputs.version
outputs.description = inputs.description
outputs.lastVersion = lastVersion
outputs.traffic = traffic

return outputs
}

module.exports = {
getType,
getDefaultProtocol,
generateId,
prepareInputs,
prepareAliasInputs,
getDefaultZipPath
}

0 comments on commit e939be3

Please sign in to comment.