Skip to content

Commit 39e5170

Browse files
author
subhankar
committed
[CD #86 #85 #44] Update CD pipeline, and cleanup
1 parent d37dd12 commit 39e5170

19 files changed

+403
-355
lines changed

.gitlab-ci.yml

-11
This file was deleted.

.travis.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,19 @@ before_script:
2626
- psql -U postgres -c "create database dpr_db owner=dpr_user;"
2727

2828
install:
29-
- pip install -r requirements.dev.txt
29+
- pip install -r requirements.txt
30+
- pip install -r requirements.test.txt
3031

3132
script: nosetests tests --with-coverage --cover-package=app
3233

3334
after_success:
3435
coveralls
35-
36+
before_deploy:
37+
- export FLASK_CONFIGURATION=stage
3638
deploy:
3739
skip_cleanup: true
3840
provider: script
39-
script: bash zappa_deploy.sh
41+
script: python zappa_deploy.py
4042
on:
4143
repo: frictionlessdata/dpr-api
4244
branch: master

README.md

+15-8
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,26 @@ Requirement python 2.7
99
```
1010
$ virtualenv env
1111
$ source env/bin/activate
12-
For dev use
13-
$ pip install -r requirements.dev.txt
12+
For test use
13+
$ pip install -r requirements.txt
14+
$ pip install -r requirements.test.txt
1415
else
1516
$ pip install -r requirements.txt
1617
```
1718

1819
## Environment Setting:
1920
Plz put .env file in root directory and add environment variables to that
2021
```
21-
API_KEY=
22-
AWS_ACCESS_KET_ID=
22+
AWS_ACCESS_KEY_ID=
2323
AWS_SECRET_ACCESS_KEY=
2424
AWS_REGION=
2525
AUTH0_CLIENT_ID=
2626
AUTH0_CLIENT_SECRET=
2727
AUTH0_DOMAIN=
2828
AUTH0_DB_NAME=
29-
AUTH0_LOGIN_PAGE=
30-
AUTH0_CALLBACK_URL=
29+
AUTH0_API_AUDIENCE=
3130
S3_BUCKET_NAME=
31+
FLASKS3_BUCKET_NAME=
3232
SQLALCHEMY_DATABASE_URI=
3333
```
3434
Rename the env.template file to .env file.
@@ -63,10 +63,10 @@ The lambda configuration is in zappa_settings.json
6363
There are different environment to deploy.
6464

6565
# Right now only dev env config is there.
66-
$ zappa deploy dev [This is for first time deployment]
66+
$ zappa deploy stage [This is for first time deployment]
6767

6868
For further deployment:
69-
$ zappa update dev
69+
$ zappa update stage
7070

7171
##### Zappa Configuration:
7272
```
@@ -82,6 +82,13 @@ All api documentation is maintained by [flasgger](https://github.com/rochacbruno
8282
The swagger UI Url path is {host}/apidocs/index.html
8383

8484
## Testing:
85+
Before running tests plz run:
86+
```
87+
$ export FLASK_CONFIGURATION=test
88+
```
89+
. So that tests are not dependent on any env variable. By default it is dependent on
90+
local postgresql instance.
91+
8592
All tests are in tests directory. We use nose for testing
8693

8794
To run all tests plz use ```nosetests tests``` from the base directory.

app/mod_api/models.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from sqlalchemy import ForeignKey
1212
from sqlalchemy import UniqueConstraint
1313

14-
from sqlalchemy.dialects.postgresql import JSON
1514
from flask import current_app as app
1615
from sqlalchemy.orm import relationship
1716

@@ -108,7 +107,8 @@ class Publisher(db.Model):
108107

109108
packages = relationship("MetaDataDB", back_populates="publisher")
110109

111-
users = relationship("PublisherUser", back_populates="publisher")
110+
users = relationship("PublisherUser", back_populates="publisher",
111+
cascade='save-update, merge, delete, delete-orphan')
112112

113113

114114
class User(db.Model):
@@ -123,7 +123,8 @@ class User(db.Model):
123123
full_name = db.Column(db.TEXT)
124124
auth0_id = db.Column(db.TEXT, index=True)
125125

126-
publishers = relationship("PublisherUser", back_populates="user")
126+
publishers = relationship("PublisherUser", back_populates="user",
127+
cascade='save-update, merge, delete, delete-orphan')
127128

128129
@property
129130
def serialize(self):
@@ -187,13 +188,15 @@ class MetaDataDB(db.Model):
187188
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
188189
created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)
189190
name = db.Column(db.TEXT, index=True)
190-
descriptor = db.Column(JSON)
191+
descriptor = db.Column(db.JSON)
191192
status = db.Column(db.TEXT, index=True)
192193
private = db.Column(db.Boolean)
193194
readme = db.Column(db.TEXT)
194195

195196
publisher_id = db.Column(db.Integer, ForeignKey('publisher.id'))
196-
publisher = relationship("Publisher", back_populates="packages")
197+
publisher = relationship("Publisher", back_populates="packages",
198+
cascade="save-update, merge, delete, delete-orphan",
199+
single_parent=True)
197200

198201
__table_args__ = (
199202
UniqueConstraint("name", "publisher_id"),

app/utils/auth0_helper.py

+43-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,49 @@ def get_user(user_id):
5151
return response.json()
5252

5353

54+
def search_user(field, value):
55+
headers = {'Authorization': "Bearer {token}".
56+
format(token=get_auth0_token(None)),
57+
'content-type': "application/json"}
58+
url = "{AUDIENCE}users?include_fields=true&q={FIELD}:{VALUE}".\
59+
format(AUDIENCE=app.config["AUTH0_API_AUDIENCE"],
60+
FIELD=field, VALUE=value)
61+
response = requests.get(url=url, headers=headers)
62+
if response.ok:
63+
return response.json()
64+
else:
65+
return None
66+
67+
68+
def delete_user(user_id):
69+
headers = {'Authorization': "Bearer {token}".
70+
format(token=get_auth0_token(None)),
71+
'content-type': "application/json"}
72+
url = "{AUDIENCE}users/{USER_ID}".\
73+
format(AUDIENCE=app.config["AUTH0_API_AUDIENCE"],
74+
USER_ID=user_id)
75+
requests.delete(url=url, headers=headers)
76+
77+
78+
def create_user(email, full_name, user_name, password):
79+
80+
payload = dict(user_metadata=dict(full_name=full_name),
81+
connection=app.config['AUTH0_DB_NAME'],
82+
email=email,
83+
username=user_name,
84+
password=password)
85+
headers = {'Authorization': "Bearer {token}". \
86+
format(token=get_auth0_token(None)),
87+
'content-type': "application/json"}
88+
url = "{AUDIENCE}users".format(AUDIENCE=app.config["AUTH0_API_AUDIENCE"])
89+
response = requests.post(url=url, data=json.dumps(payload),
90+
headers=headers)
91+
if response.ok:
92+
return response.json()
93+
else:
94+
return None
95+
96+
5497
def update_user_secret(user_id):
5598
headers = {'Authorization': "Bearer {token}".\
5699
format(token=get_auth0_token(None)),
@@ -89,7 +132,6 @@ def get_auth0_token(jwt_token):
89132
token_payload = {
90133
'client_id': app.config['AUTH0_CLIENT_ID'],
91134
'client_secret': app.config['AUTH0_CLIENT_SECRET'],
92-
'redirect_uri': app.config['AUTH0_CALLBACK_URL'],
93135
'grant_type': 'client_credentials',
94136
'audience': app.config['AUTH0_API_AUDIENCE']
95137
}

env.template

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
API_KEY=
21
AWS_ACCESS_KEY_ID=
32
AWS_SECRET_ACCESS_KEY=
43
AWS_REGION=
54
AUTH0_CLIENT_ID=
65
AUTH0_CLIENT_SECRET=
76
AUTH0_DOMAIN=
87
AUTH0_DB_NAME=
9-
AUTH0_LOGIN_PAGE=
10-
AUTH0_CALLBACK_URL=
118
AUTH0_API_AUDIENCE=
129
S3_BUCKET_NAME=
10+
FLASKS3_BUCKET_NAME=
1311
SQLALCHEMY_DATABASE_URI=

manager.py

+55-12
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
from app.database import db
1313
from app.mod_api import models
1414
from app import create_app
15-
from app.mod_api.models import MetaDataDB, Publisher, PublisherUser
15+
from app.mod_api.models import MetaDataDB, Publisher, \
16+
PublisherUser, User, BitStore
17+
from app.utils import auth0_helper
1618

1719
dot_env_path = join(dirname(__file__), '.env')
1820
load_dotenv(dot_env_path)
@@ -44,25 +46,66 @@ def dropdb():
4446

4547
@manager.command
4648
def populate():
47-
data = json.loads(open('fixtures/datapackage.json').read())
48-
readme = open('fixtures/README.md').read()
49-
user = models.User()
50-
user.auth0_id, user.email, user.name, user.secret, user.full_name \
51-
= "auth0|123", "[email protected]", "test", \
52-
"c053521f4f3331908d89df39bba922190a69f0ea99f7ca00", "Test Bob"
53-
publisher = Publisher(name='demo')
5449

55-
metadata = MetaDataDB(name="demo-package")
56-
metadata.descriptor, metadata.status, metadata.private, metadata.readme \
57-
= json.dumps(data), 'active', False, readme
58-
publisher.packages.append(metadata)
50+
user_name, full_name, email = 'admin', 'Test Admin', '[email protected]'
51+
auth0_id = 'abc' #populate_auth0(user_name, full_name, email)
52+
populate_db(auth0_id, email, user_name, full_name)
53+
populate_data(user_name)
54+
55+
56+
def populate_auth0(user_name, full_name, email):
57+
responses = auth0_helper.search_user('username', user_name)
58+
if len(responses) > 0:
59+
for response in responses:
60+
print (response)
61+
auth0_helper.delete_user(response['user_id'])
62+
user_create = auth0_helper.create_user(email, full_name,
63+
user_name, 'Admin123')
64+
return user_create['user_id']
65+
66+
67+
def populate_db(auth0_id, email, user_name, full_name):
68+
user = User.query.filter_by(name=user_name).first()
69+
70+
publisher = Publisher.query.filter_by(name=user_name).first()
71+
if publisher:
72+
db.session.delete(publisher)
73+
db.session.commit()
74+
if user:
75+
db.session.delete(user)
76+
db.session.commit()
77+
78+
user = User()
79+
user.auth0_id, user.email, user.name, user.full_name, user.secret \
80+
= auth0_id, email, user_name, full_name, \
81+
"c053521f4f3331908d89df39bba922190a69f0ea99f7ca00"
82+
83+
publisher = Publisher(name=user_name)
5984
association = PublisherUser(role="OWNER")
6085
association.publisher = publisher
6186
user.publishers.append(association)
6287

6388
db.session.add(user)
89+
db.session.commit()
6490

91+
92+
def populate_data(publisher_name):
93+
data = json.loads(open('fixtures/datapackage.json').read())
94+
data_csv = open('fixtures//data/demo-resource.csv').read()
95+
readme = open('fixtures/README.md').read()
96+
publisher = Publisher.query.filter_by(name=publisher_name).one()
97+
metadata = MetaDataDB(name="demo-package")
98+
metadata.descriptor, metadata.status, metadata.private, metadata.readme \
99+
= json.dumps(data), 'active', False, readme
100+
101+
publisher.packages.append(metadata)
102+
db.session.add(publisher)
65103
db.session.commit()
104+
bitstore = BitStore(publisher_name, package='demo-package')
105+
key = bitstore.build_s3_key('demo-resource.csv')
106+
bucket_name = app.config['S3_BUCKET_NAME']
107+
s3_client = app.config['S3']
108+
s3_client.put_object(Bucket=bucket_name, Key=key, Body=data_csv)
66109

67110
if __name__ == "__main__":
68111
manager.run()

migrations/alembic.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[alembic]
44
# template used to generate migration files
5-
file_template = %%(rev)s_%%(slug)s
5+
# file_template = %%(rev)s_%%(slug)s
66

77
# set to 'true' to run the environment during
88
# the 'revision' command, regardless of autogenerate

migrations/versions/9f755c367f6d_.py

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""empty message
2+
3+
Revision ID: 9f755c367f6d
4+
Revises: None
5+
Create Date: 2016-11-21 13:16:22.753496
6+
7+
"""
8+
9+
# revision identifiers, used by Alembic.
10+
revision = '9f755c367f6d'
11+
down_revision = None
12+
13+
from alembic import op
14+
import sqlalchemy as sa
15+
from sqlalchemy.dialects import postgresql
16+
17+
def upgrade():
18+
### commands auto generated by Alembic - please adjust! ###
19+
op.create_table('publisher',
20+
sa.Column('id', sa.Integer(), nullable=False),
21+
sa.Column('created_at', sa.DateTime(), nullable=True),
22+
sa.Column('name', sa.TEXT(), nullable=False),
23+
sa.Column('title', sa.Text(), nullable=True),
24+
sa.PrimaryKeyConstraint('id')
25+
)
26+
op.create_index(op.f('ix_publisher_name'), 'publisher', ['name'], unique=True)
27+
op.create_table('user',
28+
sa.Column('id', sa.Integer(), nullable=False),
29+
sa.Column('created_at', sa.DateTime(), nullable=True),
30+
sa.Column('email', sa.TEXT(), nullable=True),
31+
sa.Column('secret', sa.TEXT(), nullable=True),
32+
sa.Column('name', sa.TEXT(), nullable=False),
33+
sa.Column('full_name', sa.TEXT(), nullable=True),
34+
sa.Column('auth0_id', sa.TEXT(), nullable=True),
35+
sa.PrimaryKeyConstraint('id')
36+
)
37+
op.create_index(op.f('ix_user_auth0_id'), 'user', ['auth0_id'], unique=False)
38+
op.create_index(op.f('ix_user_email'), 'user', ['email'], unique=False)
39+
op.create_index(op.f('ix_user_name'), 'user', ['name'], unique=True)
40+
op.create_table('package',
41+
sa.Column('id', sa.Integer(), nullable=False),
42+
sa.Column('created_at', sa.DateTime(), nullable=True),
43+
sa.Column('name', sa.TEXT(), nullable=True),
44+
sa.Column('descriptor', postgresql.JSON(astext_type=sa.Text()), nullable=True),
45+
sa.Column('status', sa.TEXT(), nullable=True),
46+
sa.Column('private', sa.Boolean(), nullable=True),
47+
sa.Column('readme', sa.TEXT(), nullable=True),
48+
sa.Column('publisher_id', sa.Integer(), nullable=True),
49+
sa.ForeignKeyConstraint(['publisher_id'], [u'publisher.id'], ),
50+
sa.PrimaryKeyConstraint('id'),
51+
sa.UniqueConstraint('name', 'publisher_id')
52+
)
53+
op.create_index(op.f('ix_package_name'), 'package', ['name'], unique=False)
54+
op.create_index(op.f('ix_package_status'), 'package', ['status'], unique=False)
55+
op.create_table('publisher_user',
56+
sa.Column('id', sa.Integer(), nullable=False),
57+
sa.Column('created_at', sa.DateTime(), nullable=True),
58+
sa.Column('user_id', sa.Integer(), nullable=False),
59+
sa.Column('publisher_id', sa.Integer(), nullable=False),
60+
sa.Column('role', sa.TEXT(), nullable=False),
61+
sa.ForeignKeyConstraint(['publisher_id'], [u'publisher.id'], ),
62+
sa.ForeignKeyConstraint(['user_id'], [u'user.id'], ),
63+
sa.PrimaryKeyConstraint('id', 'user_id', 'publisher_id')
64+
)
65+
### end Alembic commands ###
66+
67+
68+
def downgrade():
69+
### commands auto generated by Alembic - please adjust! ###
70+
op.drop_table('publisher_user')
71+
op.drop_index(op.f('ix_package_status'), table_name='package')
72+
op.drop_index(op.f('ix_package_name'), table_name='package')
73+
op.drop_table('package')
74+
op.drop_index(op.f('ix_user_name'), table_name='user')
75+
op.drop_index(op.f('ix_user_email'), table_name='user')
76+
op.drop_index(op.f('ix_user_auth0_id'), table_name='user')
77+
op.drop_table('user')
78+
op.drop_index(op.f('ix_publisher_name'), table_name='publisher')
79+
op.drop_table('publisher')
80+
### end Alembic commands ###

0 commit comments

Comments
 (0)