Skip to content

Commit

Permalink
Merge pull request #3462 from lakshmi-kannan/lakshmi/openapi_spec_lint
Browse files Browse the repository at this point in the history
OpenAPI spec linter #2 (Circle CI check)
  • Loading branch information
Kami committed Jun 26, 2017
2 parents 02a02ac + ddb8cb3 commit 08a2321
Show file tree
Hide file tree
Showing 13 changed files with 4,581 additions and 55 deletions.
19 changes: 18 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,23 @@ configgen:
. $(VIRTUALENV_DIR)/bin/activate; pylint -E --rcfile=./lint-configs/python/.pylintrc --load-plugins=pylint_plugins.api_models tools/*.py || exit 1;
. $(VIRTUALENV_DIR)/bin/activate; pylint -E --rcfile=./lint-configs/python/.pylintrc pylint_plugins/*.py || exit 1;

.PHONY: lint-api-spec
lint-api-spec: requirements .lint-api-spec

.PHONY: .lint-api-spec
.lint-api-spec:
@echo
@echo "================== Lint API spec ===================="
@echo
. $(VIRTUALENV_DIR)/bin/activate; st2common/bin/st2-validate-api-spec --generate

.PHONY: circle-lint-api-spec
circle-lint-api-spec:
@echo
@echo "================== Lint API spec ===================="
@echo
. $(VIRTUALENV_DIR)/bin/activate; st2common/bin/st2-validate-api-spec --generate || echo "Open API spec lint failed."

.PHONY: flake8
flake8: requirements .flake8

Expand Down Expand Up @@ -417,7 +434,7 @@ debs:
ci: ci-checks ci-unit ci-integration ci-mistral ci-packs-tests

.PHONY: ci-checks
ci-checks: compile pylint flake8 bandit .st2client-dependencies-check .st2common-circular-dependencies-check .rst-check
ci-checks: compile pylint flake8 bandit .st2client-dependencies-check .st2common-circular-dependencies-check circle-lint-api-spec .rst-check

.PHONY: .rst-check
.rst-check:
Expand Down
1 change: 1 addition & 0 deletions fixed-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ zake==0.2.2
routes==2.3.1
flex==6.5.0
webob==1.6.0
prance==0.5.1
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ oslo.config<1.13,>=1.12.1
oslo.utils<3.1.0
paramiko<2.2,>=2.1.2
passlib==1.6.5
prance==0.5.1
prettytable
prompt-toolkit==1.0.7
psutil
Expand Down
2 changes: 1 addition & 1 deletion st2api/st2api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def setup_app(config={}):

router = Router(debug=cfg.CONF.api.debug, auth=cfg.CONF.auth.enable)

spec = spec_loader.load_spec('st2common', 'openapi.yaml')
spec = spec_loader.load_spec('st2common', 'openapi.yaml.j2')
transforms = {
'^/api/v1/': ['/', '/v1/'],
'^/api/v1/executions': ['/actionexecutions', '/v1/actionexecutions'],
Expand Down
2 changes: 1 addition & 1 deletion st2auth/st2auth/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def setup_app(config={}):

router = Router(debug=cfg.CONF.auth.debug)

spec = spec_loader.load_spec('st2common', 'openapi.yaml')
spec = spec_loader.load_spec('st2common', 'openapi.yaml.j2')
transforms = {
'^/auth/v1/': ['/', '/v1/']
}
Expand Down
21 changes: 21 additions & 0 deletions st2common/bin/st2-validate-api-spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python2.7
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys
from st2common.cmd.validate_api_spec import main

if __name__ == '__main__':
sys.exit(main())
1 change: 1 addition & 0 deletions st2common/in-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ git+https://github.com/Kami/entrypoints.git@dont_use_backports#egg=entrypoints
routes
flex
webob
prance
119 changes: 119 additions & 0 deletions st2common/st2common/cmd/validate_api_spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
A script that validates each entry defined in OpenAPI-Spec for st2 APIs
(in st2common/openapi.yaml) has a corresponding API model class defined
in st2common/models/api/.
"""

import os

from oslo_config import cfg
from prance import ResolvingParser

from st2common import config
from st2common import log as logging
from st2common.util import spec_loader
from st2common.script_setup import setup as common_setup
from st2common.script_setup import teardown as common_teardown


__all__ = [
'main'
]


cfg.CONF.register_cli_opt(
cfg.StrOpt('spec-file', short='f', required=False,
default='st2common/st2common/openapi.yaml')
)

cfg.CONF.register_cli_opt(
cfg.BoolOpt('generate', short='-c', required=False,
default=False)
)

LOG = logging.getLogger(__name__)


def setup():
common_setup(config=config, setup_db=False, register_mq_exchanges=False)


def _validate_definitions(spec):
defs = spec.get('definitions', None)
error = False
verbose = cfg.CONF.verbose

for (model, definition) in defs.iteritems():
api_model = definition.get('x-api-model', None)

if not api_model:
msg = (
'API model field "x-api-model" not defined for definition "%s".' % model
)

if verbose:
LOG.info('Supplied definition for model %s: \n\n%s.', model, definition)

error = True
LOG.error(msg)

return error


def validate_spec():
spec_file = cfg.CONF.spec_file
generate_spec = cfg.CONF.generate

if not os.path.exists(spec_file) and not generate_spec:
msg = ('No spec file found in location %s. ' % spec_file +
'Provide a valid spec file or ' +
'pass --generate-api-spec to genrate a spec.')
raise Exception(msg)

if generate_spec:
if not spec_file:
raise Exception('Supply a path to write to spec file to.')

spec_string = spec_loader.generate_spec('st2common', 'openapi.yaml.j2')

with open(spec_file, 'w') as f:
f.write(spec_string)
f.flush()

parser = ResolvingParser(spec_file)
spec = parser.specification

return _validate_definitions(spec)


def teartown():
common_teardown()


def main():
setup()

try:
ret = validate_spec()
except Exception as e:
LOG.error(e.message)
ret = 1
finally:
teartown()

return ret
Loading

0 comments on commit 08a2321

Please sign in to comment.