Skip to content

Commit

Permalink
Merge pull request #128 from aliyun/tanhehe/add_nas_file_manager_demo
Browse files Browse the repository at this point in the history
add nas file manager application demo
  • Loading branch information
tanhe123 committed Jan 9, 2019
2 parents 0361b98 + fbfd046 commit 7a46471
Show file tree
Hide file tree
Showing 8 changed files with 343 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ examples/java/demo/target/
examples/local/java8/target/*
!examples/local/java8/target/demo-1.0-SNAPSHOT.jar

examples/nas_browser/src/*
!examples/nas_browser/src/index.py

.idea/
.vscode/

Expand Down
1 change: 1 addition & 0 deletions README-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Fun 作为一个命令行工具,内置了多个子命令,比如 config、loc
- [开发函数计算的正确姿势 —— 本地运行、调试、发布 NAS 函数](https://yq.aliyun.com/articles/683684): 介绍了如何在本地运行、单步调试配置了 NAS 服务的函数。
- [开发函数计算的正确姿势 —— Api 本地运行调试](https://yq.aliyun.com/articles/683685): 介绍了如何在通过 API 在本地运行、单步调试函数。
- [开发函数计算的正确姿势 —— 开发 WordPress 应用](https://yq.aliyun.com/articles/683686): 通过一个实战场景,介绍了如何利用 Fun 工具本地开发 WordPress Web 应用。
- [开发函数计算的正确姿势 —— 开发 NAS 文件管理应用](https://yq.aliyun.com/articles/685803): 介绍了如何使用 Fun Local 开发一个 NAS 文件管理 Web 应用。
- [Fun 规范文档](https://github.com/aliyun/fun/blob/master/docs/specs/2018-04-03-zh-cn.md): 详细介绍了 Fun 规范文档的细节。
- [常见问题与解答](https://github.com/aliyun/fun/blob/master/docs/usage/faq-zh.md): 使用 Fun 时的常见问题与解答。
- [更多示例](https://github.com/aliyun/fun/tree/master/examples)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ We have prepared a series of tutorials to help you use the Fun tool more easily:
- [开发函数计算的正确姿势 —— 本地运行、调试、发布 NAS 函数](https://yq.aliyun.com/articles/683684): Demonstrates how to run and debug functions configured with NAS services locally.
- [开发函数计算的正确姿势 —— Api 本地运行调试](https://yq.aliyun.com/articles/683685): Demonstrates how to run and debug functions locally through the API.
- [开发函数计算的正确姿势 —— 开发 WordPress 应用](https://yq.aliyun.com/articles/683686): Demonstrates how to develop and debug a WordPress web application locally.
- [开发函数计算的正确姿势 —— 开发 NAS 文件管理应用](https://yq.aliyun.com/articles/685803): Demonstrates how to develop and debug a NAS file manager web application locally.
- [Specification](https://github.com/aliyun/fun/blob/master/docs/specs/2018-04-03.md): Introduces the syntax of the fun's template.yml file.
- [FAQ](https://github.com/aliyun/fun/blob/master/docs/usage/faq.md): Frequently asked questions and answers when using fun.
- [More Examples](https://github.com/aliyun/fun/tree/master/examples)
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/getting_started-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

## 示例

下面我们用一个简单的 helloworld 示例演示 fun 如何使用。首先在项目根目录下创建一个 hello.js 文件。
下面我们用一个简单的 helloworld 示例演示 fun 如何使用。首先在项目根目录下创建一个 helloworld.js 文件。

```javascript
exports.handler = function(event, context, callback) {
Expand Down
1 change: 1 addition & 0 deletions examples/nas_browser/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# code for https://yq.aliyun.com/articles/685803
144 changes: 144 additions & 0 deletions examples/nas_browser/nas.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/bin/bash

set -e

SHELL_DIR="$(dirname $0)"

usage() {
echo "usage:"
echo -e "\t./nas.sh cp <src> fc:<dst>"
echo -e "\t./nas.sh cp oss://<bucket>/<object> fc:<dst>"
echo -e "\t./nas.sh ls <path>"
echo -e "\t./nas.sh cat <path>"
echo -e "\t./nas.sh unzip <path>"
echo -e "\t./nas.sh bash <cmd>"
}

ENV_FILE=$(pwd)/.env

if [ -f $ENV_FILE ]; then
. $ENV_FILE
fi

FC_URL=${FC_URL:-http://localhost:8000/2016-08-15/proxy/nasDemo/browser/}

checkArgs() {
if [ -z "$1" ]; then
usage
exit -1
fi
}

cp() {
checkArgs $1
checkArgs $2

src=$1
dst=$2


if [[ "$dst" =~ ^'fc:/' ]]; then
dstFile=${dst#fc:}
else
echo "dst must start with fc:/ prefix";
exit 1
fi

if [[ "$src" =~ ^'oss:' ]]; then
ossFile=$src

curl -G -XPOST \
$FC_URL"cp" \
--data-urlencode "dst=$dstFile" \
--data-urlencode "oss=$ossFile"

exit 0
fi

if [[ "$src" =~ ^'/' ]]; then
absSrcFile=$src
elif [[ "$src" =~ ^'~' ]]; then
absSrcFile=$HOME${dst#~}
else
currentDir=$(pwd)
absSrcFile=$currentDir/$src
fi

if [ ! -f "$absSrcFile" ]; then
echo "file $absSrcFile not found."
fi

curl -XPOST \
$FC_URL"cp?dst=$dstFile" \
-F "file=@$absSrcFile"
}

ls() {
dstDir=$1

if [[ "$dstDir" =~ ^'fc:/' ]]; then
dstDir=${dstDir#fc:}

curl -G -XGET \
$FC_URL"ls" \
--data-urlencode "p=$dstDir"
else
echo "file must start with fc:/ prefix";
exit 1
fi
}

cat() {
file=$1

if [[ "$file" =~ ^'fc:/' ]]; then
file=${file#fc:}

curl -G -XGET \
$FC_URL"cat" \
--data-urlencode "file=$file"
else
echo "file must start with fc:/ prefix";
exit 1
fi
}

bash() {
cmd=$(echo "$*")
checkArgs $cmd

curl -G -XPOST \
$FC_URL"bash" \
--data-urlencode "cmd=$cmd"
}

unzip() {
checkArgs $1
zipFile=$1

if [[ "$zipFile" =~ ^'fc:/' ]]; then
zipFile=${zipFile#fc:}

curl -G -XPOST \
$FC_URL"unzip" \
--data-urlencode "file=$zipFile"
else
echo "file must start with fc:/ prefix";
exit 1
fi
}

case "$1" in
cp ) cp $2 $3;;
ls ) ls $2;;
cat ) cat $2;;
unzip ) unzip $2;;
bash ) shift; bash $@;;
-- ) shift; break ;;
"" ) usage ;;
* ) usage; exit -1 ;;
esac




155 changes: 155 additions & 0 deletions examples/nas_browser/src/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/usr/bin/env python
# coding=utf-8
from flask import Flask
from flask import request
from flask import make_response
from flask import send_from_directory, send_file
import subprocess

import oss2
import sys
import os
import zipfile

import logging

logger = logging.getLogger()

app = Flask(__name__)

@app.route('/ls', methods=['GET'])
def ls(p = ''):
p = request.args.get('p', default = '', type=str)

path = os.path.join('/', p)

if os.path.isdir(path):
dirs = os.listdir(path)
elif os.path.isfile(path):
dirs = [os.path.basename(path)]
else:
return make_response('invliad path')

resp = make_response('\n'.join(dirs), 200)
return resp

@app.route('/cp', methods=['POST'])
def cp():

p = request.args.get('dst', default = '', type=str)

logger.info("cp path parameter is " + p)

path = os.path.join('/', p)

oss_url = request.args.get('oss', default = '', type=str)

if oss_url:
if os.path.isdir(path):
return make_response('dir is not support')

global auth
oss_endpoint = os.getenv('OSS_ENDPOINT')

bucket_and_object = oss_url[len('oss://'):]

index = bucket_and_object.index('/')
bucket = bucket_and_object[:index]
object_key = bucket_and_object[index + 1:]

logger.info('oss endpoint is ' + oss_endpoint)
logger.info('bucket is ' + bucket)
logger.info('object_key is ' + object_key)

bucket = oss2.Bucket(auth, oss_endpoint, bucket)

bucket.get_object_to_file(object_key, path)

return make_response('copy from ' + oss_url + ' to fc:' + path)
else:
f = request.files['file']

if path.endswith('/') or os.path.isdir(path):
dst = os.path.join(path, f.filename)
else:
dst = path

f.save(dst)

html = f.filename + ' upload ' + dst + ' to success'
return make_response(html, 200)

@app.route('/cat', methods=['GET'])
def cat():

f = request.args.get('file', default = '', type=str)

path = os.path.join('/', f)

if os.path.isfile(path):
return send_file(path)
else:
return make_response("file " + path + " not exist", 200)

@app.route('/bash', methods=['POST'])
def bash():

cmd = request.args.get('cmd', default = '', type=str)

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p.wait()

rs = ''.join(p.stdout.readlines())

return make_response(rs, 200)

@app.route('/unzip', methods=['POST'])
def unzip():

f = request.args.get('file', default = '', type=str)

if not os.path.isfile(f):
return make_response('file ' + f + ' is not exist', 400)

if not f.endswith('.zip'):
return make_response('file ' + f + ' is not zip file', 400)

extract_folder = f[:-4]

if not os.path.exists(extract_folder):
os.mkdir(extract_folder)

logger.info('zip file is ' + f)

logger.info('extract_folder is ' + extract_folder)

logger.info('begin unzip...')

with zipfile.ZipFile(f, 'r') as z:
z.extractall(extract_folder)
logger.info('after unzip...')

return make_response('extract file ' + f + ' to folder ' + extract_folder + ' success')

@app.errorhandler(Exception)
def all_exception_handler(error):
return make_response(str(error), 500)

def handler(environ, start_response):

context = environ['fc.context']
creds = context.credentials

local = bool(os.getenv('local', ""))

global auth

if (local):
auth = oss2.Auth(creds.access_key_id,
creds.access_key_secret)
else:
auth = oss2.StsAuth(creds.access_key_id,
creds.access_key_secret,
creds.security_token)

return app(environ, start_response)
37 changes: 37 additions & 0 deletions examples/nas_browser/template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
nasDemo:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'fc nas test'
Policies:
- AliyunECSNetworkInterfaceManagementAccess
- AliyunOSSFullAccess
VpcConfig:
VpcId: 'vpc-bp12hm92gdpcjtai7ua82'
VSwitchIds: [ 'vsw-bp1gitru7oicyyb4uiylj' ]
SecurityGroupId: 'sg-bp1243pi65bw4cjj4bks'
NasConfig:
UserId: 10003
GroupId: 10003
MountPoints:
- ServerAddr: '012194b28f-ujc20.cn-hangzhou.nas.aliyuncs.com:/'
MountDir: '/mnt/nas'

browser:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: index.handler
Runtime: python2.7
CodeUri: './src'
Timeout: 100
EnvironmentVariables:
ROOT_DIR: /mnt/nas
OSS_ENDPOINT: oss-cn-shanghai.aliyuncs.com
Events:
http-test:
Type: HTTP
Properties:
AuthType: ANONYMOUS
Methods: ['GET', 'POST', 'PUT']

0 comments on commit 7a46471

Please sign in to comment.