By Jiangyu (Alibaba Cloud Serverless Product Manager)
Serverless Devs have been building in the open-source code and open ecosystem mode. There are two ways for community users to participate in the construction of Serverless Devs:
You need to know about Serverless Registry before talking about Serverless Devs Packages. Many R&D know that different languages/ecosystems have different package management platforms (such as Pypi in Python and NPM in Node.js).
The so-called package management platform, roughly speaking, aims to manage packages. The packages here often refer to certain functions or capabilities that others have encapsulated and can be directly used.
Here are two vivid examples. If we are engaged in artificial intelligence, it is not realistic to write various algorithms manually. We often use corresponding packages (such as Sklearn and Tensorflow) to load certain models quickly and then develop and perfect them on this basis.
We also hope to have a similar package management platform in the Serverless field, which is Serverless Registry:
Serverless Registry | Python Pypi | Nodejs NPM | |
Storage Content | Serverless packages (including components and applications) | Python packages | Nodejs packages |
Open or Not | Yes | Yes | Yes |
Official Source | registry.devsapp.cn/simple | pypi.python.org | registry.npmjs.org |
Examples of Other Sources | Github registry, Gitee registry | Tsinghua source, Douban source | tnpm, cnpm |
Private Deployment | Supported | Supported | Supported |
Tools | Serverless Devs | pip | npm |
Commands | s | pip | npm |
Usage | Direct reference in s.yaml
|
Reference in code after installation | Reference in code after installation |
Unlike Python's Pypi and Node.js's NPM, in Serverless Registry, packages are divided into two types: Component and Application.
To distinguish between Component and Application:
Here is the difference between them in the Serverless Devs specification:
The relationship between Component and Application is that Application is the definition of an application case and needs to be deployed and launched through Component.
Perhaps the expression is somewhat abstract. It can be explained by a vivid case. Examples:
The process to develop Serverless Packages is relatively simple because relatively complete scaffolding capabilities are provided in the Serverless Devs developer tools.
The developer only needs to execute the s init
and select the Dev Template for Serverless Devs
.
After the selection is completed, it is not difficult to find that we will continue to choose whether to develop a Component or an Application.
After selecting Component Scaffolding
, you need to give the Component to be developed a name (such as deployfunction
).
At this time, you can enter the project directory of Component according to the system prompt:
You can open the current project through the IDE and perform dependency installation through the npm
. (Serverless Devs is a Typescript-based project, so the development of components only supports Typescript and Node.js languages.)
At this point, you can open the src/index.ts
file in the project, and it is easy to find that there is already a case:
import logger from './common/logger';
import { InputProps } from './common/entity';
export default class ComponentDemo {
/**
* demo instance
* @param inputs
* @returns
*/
public async test(inputs: InputProps) {
logger.debug(`input: ${JSON.stringify(inputs.props)}`);
logger.info('command test');
return { hello: 'world' };
}
}
In this file, we can find a test (inputs)
method. It is a case of printing inputs
parameters and returning hello world
. We can learn several things through this simple case:
In a project, we can write multiple methods to expose to the outside. Currently, there is only one test, but we can add any public methods that will become commands for the component. Examples:
public async test(inputs: InputProps) {
logger.debug(`input: ${JSON.stringify(inputs.props)}`);
logger.info('command test for test');
return { hello: 'world' };
}
public async deploy(inputs: InputProps) {
logger.debug(`input: ${JSON.stringify(inputs.props)}`);
logger.info('command test for deploy');
return { hello: 'world' };
}
When we use the component, it has two commands: the test command and the deploy command. We can compile the basic development state of the project to verify our idea: npm run watch
:
We can find the example directory and test the deploy method. For example:
From the s.yaml file example below, it can be seen that this yaml has two services (component-test and component-test2).
Both services use the same component. Therefore, the expected result is obtained after the s deploy
is executed, which means the deploy method is executed.
Similarly, we can execute the test command to see the effect.
In other words, when the Serverless Devs tool loads a component, it passes the corresponding parameters to the specified method and executes the method. Therefore, any function you want to achieve can be written in the corresponding method.
Let's take the Serverless Registry Component project as an example. There is a Login function, and I implemented the following in Login:
/**
* demo login
* @param inputs
* @returns
*/
public async login(inputs: InputProps) {
const apts = {
boolean: ['help'],
alias: {help: 'h'},
};
const comParse = commandParse({args: inputs.args}, apts);
if (comParse.data && comParse.data.help) {
help([{
header: 'Login',
content: `Log in to Serverless Registry`
}, {
header: 'Usage',
content: `$ s cli registry login <options>`
}, {
header: 'Options',
optionList: [
{
name: 'token',
description: '[Optional] If you already have a token, you can configure it directly',
type: String,
}
],
}, {
header: 'Examples without Yaml',
content: [
'$ s cli registry login',
'$ s cli registry login --token my-serverless-registry-token',
],
},]);
return;
}
const tempToken = comParse.data ? comParse.data.token : null
let st = 0
let user
if (tempToken) {
const fd = await fse.openSync(`${getRootHome()}/serverless-devs-platform.dat`, 'w+')
await fse.writeSync(fd, tempToken)
await fse.closeSync(fd)
st = 1
} else {
const token = random({length: 20})
const loginUrl = `https://github.com/login/oauth/authorize?client_id=beae900546180c7bbdd6&redirect_uri=http://registry.devsapp.cn/user/login/github?token=${token}`
// output remind
logger.warn("Serverless registry no longer provides independent registration function, but will uniformly adopt GitHub authorized login scheme.")
logger.info("The system will attempt to automatically open the browser for authorization......")
try {
await sleep(2000)
opn(loginUrl)
} catch (e) {
logger.info("Failed to open the default address. Please try to open the following URL manually for authorization: ")
logger.info(loginUrl)
}
await logger.task('Getting', [
{
title: 'Getting login token ...',
id: 'get token',
task: async () => {
for (let i = 0; i < 100; i++) {
await sleep(2000)
const tempResult = await request('http://registry.devsapp.cn/user/information/github', {
params: {
token: token,
},
})
if (!tempResult.Error && tempResult.safety_code) {
// or obtained as a result, the storage state
const fd = await fse.openSync(`${getRootHome()}/serverless-devs-platform.dat`, 'w+')
await fse.writeSync(fd, tempResult.safety_code)
await fse.closeSync(fd)
st = 1
user = tempResult.login
break
}
}
},
}
])
}
if (st == 1) {
logger.log(`${user ? user + ': ' : ''}Welcome to Serverless Devs Registry.`, "green");
} else {
logger.error("Login failed. Please log in to GitHub account on the pop-up page and authorize it, or try again later.")
}
return null;
}
There are several main points in this method:
inputs
parameter analysis is to obtain the user input parameter.-h
or --help
parameters, output the corresponding help information.--token
, the --token
corresponding value is stored in a file.--token
input, open the browser, access the login address of Serverless Registry, and obtain the relevant login token
.So, the same method, if it is a method or commands to deploy a function, can we package and compress the code in this method, call the relevant creation function, and update the interface of the function to create the function? Another example, if you want to make a method to delete a function, can you call the interface of the delete function in it?
Therefore, no matter what function you want to implement, it can be implemented in the corresponding method.
As mentioned before, Serverless Devs will call the method with some parameters, but what do the parameters look like? What is the format, and how should we parse it?
What is the use of the final return of the project? How do I obtain the key information of a user in a project? How do I obtain various parameters that users write in YAML? How do I get the parameters that a user passes when executing a command?
You can refer to the Component Model Code Specification of the Serverless Devs Package Development Specification Document. In the document, we can find:
The structure of the inputs parameter is:
{
"command": "",
"project": {
"projectName": "",
"component": "",
"provider": "",
"access": ""
},
"credentials": {},
"prop": {},
"args": "",
"argsObj": []
}
The meaning of these parameters:
Contents | Meaning |
command | The command that is used by the user |
project | The basic information about the project of the user |
credentials | The information about the key |
prop | The properties or parameters the user configures |
args | The parameter passed by the user (string form) |
argsObj | The parameter passed by the user (the parsed parameter is passed as an array) |
A more specific example is that in the case code above, there is a test method, which is the method of functional implementation. When the user runs the test command, the system calls the method using the related parameters. Example:
The component is named hexo
, and the core code of the component is shown in the preceding figure. It has a test method, and the YAML on the user side is listed below:
edition: 1.0.0 # The YAML specification version of the command line, which follows the Semantic Versioning specification
name: FullStack # Project name
access: xxx-account1 # Key alias
services:
HexoComponent:
component: hexo
props:
region: 'cn-hangzhou'
codeUri: './src'
When the user runs the s test mytest -a -b abc
command, the following inputs
are returned in the test
method:
{
"command": "test",
"project": {
"projectName": "HexoComponent",
"component": "hexo",
"provider": "alibaba",
"access": "release"
},
"credentials": {
"AccountID": "********",
"AccessKeyID": "********",
"AccessKeySecret": "********"
},
"prop": {
"Region": "cn-hangzhou",
"CodeUri": "./src"
},
"args": "mytest -a -b abc",
"argsObj": [
"mytest", "-a", "-b", "abc"
]
}
Then, the test method prints the log and so on and returns the final result to the command line tool: { "hello": "world" }
.
You can refer to the core package provided by Serverless Devs for more information about how to return help files, how to obtain key information, and how to parse user input content.
In the toolkit, we can see many methods to help us quickly use it.
For example, you can introduce the core package and use the corresponding getCredential
method to obtain the user's key.
default
key information will be obtained. const { getCredential } = require('@serverless-devs/core');
async function get() {
const c = await getCredential();
console.log('c', c);
}
const { getCredential } = require('@serverless-devs/core');
async function get() {
// Inputs received by the component
const inputs = {};
const c = await getCredential(inputs, 'custom', 'AccountIdByCustom', 'SecretIDByCustom');
console.log('c', c);
}
After writing our component functions, we can describe the components. The so-called component description tells Serverless Registry what component it is and what functions it has. The description is in the publish.yaml
.
You can refer to the component model metadata for the content of this file and the values of some parameters.
In addition to publish.yaml, there are other files in the directory in the Serverless Package specification.
|- src # The name of the directory can be changed.
| └ ──Code directory
|- package.json: The main must be defined.
|- publish. yaml: Project resource description
|- readme.md: Project description
|- version.md: Version update content
The following table describes the parameters in the structure.
Contents | Required | Meaning |
src | Recommended | The directory that contains all the required files to build the project in a unified manner. You can change the name of the directory and have the directory tiled under the project. We recommend using src as the directory for unified file management. |
package.json | Yes | The package.json file of Node.js, in which the handler of the component is recorded. |
publish.yaml | Yes | The Serverless Devs Package development documentation. |
readme.md | Yes | The description or the help documentation of the component |
version.md | Recommended | The version description, such as the updates of the current version |
The latest version of the specification (version 0.0.2) will be launched soon. Unlike version 0.0.1, the Properties parameter of the new version will follow the JSON Scheme specification. Please see pr#386 for more information.
After Application Scaffolding
is selected, you need to give the Application to be developed a name (such as helloworld
).
Application development in Serverless Packages is relatively simple. No matter any programming language or project, it can be packaged as an application as long as it can be deployed through Serverless Devs developer tools.
More accurately, as long as you have a project that can be directly deployed through Serverless Devs, you can:
Please refer to the application model documentation for details in this section:
Special Format: In the application model, the src/s.yaml
file that contains resources and behavior description is required for Serverless Devs to identify and use. A user must specify specific content in this file, such as the key name and the region where the user deploys business. You can refer to:
"{{ access }}"
: It reminds the user that a parameter (such as access) is required as a parameter in YAML.'{{ bucket | alibaba oss bucket }}'
: Directly remind the user that a parameter (such as a bucket) needs to be entered as a necessary parameter in YAML, and the content "alibaba oss bucket" after |
is used to explain the meaning of this parameter.For example, an application's s.yaml
is expressed as:
edition: 1.0.0
access: "{{ access }}"
services:
website-starter:
component: devsapp/website
actions:
pre-deploy:
- run: npm install
path: ./
- run: npm run build
path: ./
props:
bucket: '{{ bucket | alibaba oss bucket }}'
src:
codeUri: ./
publishDir: ./build
index: index.html
region: cn-hangzhou
hosts:
- host: auto
After you develop a Serverless Package, you can publish it to Registry.
If you want to publish to GitHub or Gitee, the method is simple:
registry through s set registry
to use the corresponding function in the client. For example, if your account in GitHub is anycodes, you can create a repository named demo. You can upload your components/applications to this repository and publish a release. Switch the registry to GitHub on the client and then:If you want to publish a package to Serverless Registry, consider using Serverless Registry Component.
(The client tool of Serverless Registry is also a component, so it can be considered that the Serverless Registry Component project is also a best practice of the current article.)
After completing the component or application development process, you need to:
s cli registry login
s cli registry publish
.Besides login and release, this project Serverless Registry Component has many other functions, such as:
As we all know, the development of a complete technical architecture cannot be separated from the empowerment of the ecological community. Whether it is Docker's Docker Hub, Python's Pypi, or Node.js's NPM, the popularity of the ecology is positively correlated with the happiness of our developers.
We hope Serverless Devs can help more people learn about Serverless architecture through an open ecosystem like Serverless Registry. We also hope more excellent packages will be widely used.
OpenYurt v0.7.0 Interpretation: Raven, A Non-intrusive Cross-Network Domain Solution
Improve Usability Comprehensively: Open Cluster Management (OCM) v0.7.0
508 posts | 48 followers
FollowAlibaba Cloud Serverless - February 17, 2023
Alibaba Cloud New Products - December 4, 2020
Alibaba Cloud Serverless - August 23, 2022
Alibaba Cloud Serverless - June 13, 2022
Alibaba Cloud Serverless - February 28, 2023
Alibaba Cloud Serverless - August 23, 2022
508 posts | 48 followers
FollowA low-code development platform to make work easier
Learn MoreHelp enterprises build high-quality, stable mobile apps
Learn MoreAlibaba Cloud (in partnership with Whale Cloud) helps telcos build an all-in-one telecommunication and digital lifestyle platform based on DingTalk.
Learn MoreAlibaba Cloud Function Compute is a fully-managed event-driven compute service. It allows you to focus on writing and uploading code without the need to manage infrastructure such as servers.
Learn MoreMore Posts by Alibaba Cloud Native Community