Merge branch 'master' into malformed
This commit is contained in:
@@ -11,6 +11,9 @@ env:
|
||||
matrix:
|
||||
- BUILDTYPE=Release
|
||||
- BUILDTYPE=Debug
|
||||
global:
|
||||
- secure: "bG4YYWMfl9API0MSRgmOaJrlGLv06tRg9KJNawBieZvBJbITPpxVGJZT3/l/SEJ+Rl15e2dRex4k+MGQlmT2SqPQxTEYWv1qxNigKPPcla7IWeNmWWqW8uVvFjdglojgBOK2k/xErVQtA4zDfi3mwSXH4DKwquXWsoEKmX2SV7M="
|
||||
- secure: "Cbvap9ubVKgjPe3hUhI6JGeDZzBXHpOG9RaYKh+SdoIPhKnlJiNOYm1egomi+e4uqJInlFKuVHTw7Ng9Cun6Zm0jIxpkSchv1GpsR7hmB3UGnGed19Dw8121FwuUaktN+4YnbVlsyd+u8EHD3+h58t4eELrLrZolM4rS7DL6caA="
|
||||
|
||||
before_install:
|
||||
- source ./scripts/setup_travis.sh
|
||||
|
||||
6
Makefile
6
Makefile
@@ -29,12 +29,16 @@ test: build/test/Makefile
|
||||
|
||||
# Runs all test cases
|
||||
run-tests: test
|
||||
(cd build/${BUILDTYPE} && exec find . -maxdepth 1 -name "test_*" -exec {} \;)
|
||||
BUILDTYPE=$(BUILDTYPE) ./scripts/run_tests.sh
|
||||
|
||||
test/%: build/test/Makefile
|
||||
$(MAKE) -C build/test BUILDTYPE=$(BUILDTYPE) V=$(V) $*
|
||||
(cd build/$(BUILDTYPE) && exec ./test_$*)
|
||||
|
||||
# build Mac OS X project for Xcode
|
||||
xtest: config.gypi clear_xcode_cache node
|
||||
deps/run_gyp test/test.gyp --depth=. -Goutput_dir=.. --generator-output=./build -f xcode
|
||||
open ./build/test/test.xcodeproj
|
||||
|
||||
##### Makefile builds ##########################################################
|
||||
|
||||
|
||||
@@ -29,14 +29,14 @@ private:
|
||||
|
||||
|
||||
private:
|
||||
#ifdef LLMR_USE_CGL
|
||||
#if LLMR_USE_CGL
|
||||
CGLContextObj gl_context;
|
||||
GLuint fbo = 0;
|
||||
GLuint fbo_depth_stencil = 0;
|
||||
GLuint fbo_color = 0;
|
||||
#endif
|
||||
|
||||
#ifdef LLMR_USE_GLX
|
||||
#if LLMR_USE_GLX
|
||||
GLXContext gl_context = nullptr;
|
||||
XVisualInfo *x_info = nullptr;
|
||||
Display *x_display = nullptr;
|
||||
|
||||
20
include/llmr/util/error.hpp
Normal file
20
include/llmr/util/error.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef LLMR_UTIL_ERROR
|
||||
#define LLMR_UTIL_ERROR
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace llmr {
|
||||
namespace error {
|
||||
|
||||
struct style_parse : std::exception {
|
||||
inline style_parse(size_t offset, const char *msg) : offset(offset), msg(msg) {}
|
||||
inline const char* what() const noexcept { return msg.c_str(); }
|
||||
const size_t offset;
|
||||
const std::string msg;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -13,7 +13,7 @@ std::string compress_png(int width, int height, void *rgba, bool flip = false);
|
||||
|
||||
class Image {
|
||||
public:
|
||||
Image(const std::string &img);
|
||||
Image(const std::string &img, bool flip = false);
|
||||
~Image();
|
||||
|
||||
inline const char *getData() const { return img; }
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace llmr {
|
||||
namespace util {
|
||||
|
||||
void write_file(const std::string &filename, const std::string &data);
|
||||
std::string read_file(const std::string &filename);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
2
llmr.gyp
2
llmr.gyp
@@ -7,7 +7,7 @@
|
||||
{
|
||||
'target_name': 'shaders',
|
||||
'type': 'none',
|
||||
# 'hard_dependency': 1,
|
||||
'hard_dependency': 1,
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'Build Shaders',
|
||||
|
||||
10
scripts/run_tests.sh
Executable file
10
scripts/run_tests.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
cd build/$BUILDTYPE
|
||||
|
||||
for TEST in test_* ; do
|
||||
./$TEST
|
||||
done
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <llmr/style/style_bucket.hpp>
|
||||
#include <llmr/util/constants.hpp>
|
||||
#include <llmr/util/time.hpp>
|
||||
#include <llmr/util/error.hpp>
|
||||
#include <csscolorparser/csscolorparser.hpp>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
@@ -102,6 +103,9 @@ void Style::loadJSON(const uint8_t *const data) {
|
||||
|
||||
rapidjson::Document doc;
|
||||
doc.Parse<0>((const char *const)data);
|
||||
if (doc.HasParseError()) {
|
||||
throw error::style_parse(doc.GetErrorOffset(), doc.GetParseError());
|
||||
}
|
||||
|
||||
StyleParser parser;
|
||||
parser.parse(const_cast<const rapidjson::Document &>(doc));
|
||||
|
||||
@@ -84,7 +84,7 @@ void warningHandler(png_structp, png_const_charp error_msg) {
|
||||
fprintf(stderr, "PNG: %s\n", error_msg);
|
||||
}
|
||||
|
||||
Image::Image(const std::string &data) {
|
||||
Image::Image(const std::string &data, bool flip) {
|
||||
Buffer buffer(data);
|
||||
|
||||
if (buffer.length < 8 || !png_check_sig((const png_bytep)buffer.data, 8)) {
|
||||
@@ -148,7 +148,7 @@ Image::Image(const std::string &data) {
|
||||
png_bytep *rows = nullptr;
|
||||
} pointers(height);
|
||||
for (unsigned i = 0; i < height; ++i) {
|
||||
pointers.rows[i] = (png_bytep)(surface + (i * rowbytes));
|
||||
pointers.rows[flip ? height - 1 - i : i] = (png_bytep)(surface + (i * rowbytes));
|
||||
}
|
||||
|
||||
// Read image data
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
#include <llmr/util/io.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
void llmr::util::write_file(const std::string &filename, const std::string &data) {
|
||||
namespace llmr {
|
||||
namespace util {
|
||||
|
||||
void write_file(const std::string &filename, const std::string &data) {
|
||||
FILE *fd = fopen(filename.c_str(), "wb");
|
||||
if (fd) {
|
||||
fwrite(data.data(), sizeof(std::string::value_type), data.size(), fd);
|
||||
@@ -11,3 +18,17 @@ void llmr::util::write_file(const std::string &filename, const std::string &data
|
||||
fprintf(stderr, "Failed to open file\n");
|
||||
}
|
||||
}
|
||||
|
||||
std::string read_file(const std::string &filename) {
|
||||
std::ifstream file(filename);
|
||||
if (file.good()) {
|
||||
std::stringstream data;
|
||||
data << file.rdbuf();
|
||||
return data.str();
|
||||
} else {
|
||||
throw std::runtime_error("Cannot read file " + filename);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
100
test/fixtures/fixture_request.cpp
vendored
Normal file
100
test/fixtures/fixture_request.cpp
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
#include <llmr/platform/platform.hpp>
|
||||
#include <llmr/platform/request.hpp>
|
||||
#include <llmr/util/uv.hpp>
|
||||
|
||||
const std::string base_directory = []{
|
||||
std::string fn = __FILE__;
|
||||
fn.erase(fn.find_last_of("/"));
|
||||
return fn;
|
||||
}();
|
||||
|
||||
|
||||
namespace llmr {
|
||||
|
||||
std::shared_ptr<platform::Request>
|
||||
platform::request_http(const std::string &url,
|
||||
std::function<void(Response *)> callback,
|
||||
std::shared_ptr<uv::loop> loop) {
|
||||
uv_loop_t *l = nullptr;
|
||||
if (loop) {
|
||||
l = **loop;
|
||||
} else {
|
||||
l = uv_default_loop();
|
||||
}
|
||||
|
||||
std::string clean_url = base_directory + "/" + url;
|
||||
auto pos = clean_url.find("://");
|
||||
if (pos != std::string::npos) {
|
||||
clean_url.replace(pos, 3, "/");
|
||||
}
|
||||
|
||||
std::replace(clean_url.begin(), clean_url.end(), '+', ' ');
|
||||
|
||||
std::shared_ptr<Request> req = std::make_shared<Request>(url, callback, loop);
|
||||
|
||||
int err;
|
||||
|
||||
uv_fs_t open_req;
|
||||
err = uv_fs_open(l, &open_req, clean_url.c_str(), O_RDONLY, S_IRUSR, nullptr);
|
||||
uv_fs_req_cleanup(&open_req);
|
||||
if (err < 0) {
|
||||
req->res->code = err;
|
||||
req->res->error_message = uv_strerror(err);
|
||||
req->complete();
|
||||
return req;
|
||||
}
|
||||
uv_file fd = err;
|
||||
|
||||
uv_fs_t stat_req;
|
||||
uv_fs_fstat(l, &stat_req, fd, nullptr);
|
||||
uv_fs_req_cleanup(&stat_req);
|
||||
err = uv_fs_fstat(l, &stat_req, fd, nullptr);
|
||||
if (err < 0) {
|
||||
req->res->code = err;
|
||||
req->res->error_message = uv_strerror(err);
|
||||
req->complete();
|
||||
return req;
|
||||
}
|
||||
|
||||
const uint64_t size = static_cast<const uv_stat_t*>(stat_req.ptr)->st_size;
|
||||
|
||||
|
||||
std::string body;
|
||||
body.resize(size);
|
||||
uv_buf_t uvbuf = uv_buf_init(const_cast<char *>(body.data()), body.size());
|
||||
|
||||
uv_fs_t read_req;
|
||||
err = uv_fs_read(l, &read_req, fd, &uvbuf, 1, 0, nullptr);
|
||||
uv_fs_req_cleanup(&read_req);
|
||||
if (err < 0) {
|
||||
req->res->code = err;
|
||||
req->res->error_message = uv_strerror(err);
|
||||
req->complete();
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
uv_fs_t close_req;
|
||||
err = uv_fs_close(l, &close_req, fd, nullptr);
|
||||
uv_fs_req_cleanup(&close_req);
|
||||
if (err < 0) {
|
||||
req->res->code = err;
|
||||
req->res->error_message = uv_strerror(err);
|
||||
req->complete();
|
||||
return req;
|
||||
}
|
||||
|
||||
req->res->body.swap(body);
|
||||
req->res->code = 200;
|
||||
req->complete();
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
void platform::cancel_request_http(const std::shared_ptr<Request> &req) {
|
||||
if (req) {
|
||||
req->cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llmr
|
||||
BIN
test/fixtures/glyphs/Open Sans Semibold, Arial Unicode MS Bold/0-255.pbf
vendored
Normal file
BIN
test/fixtures/glyphs/Open Sans Semibold, Arial Unicode MS Bold/0-255.pbf
vendored
Normal file
Binary file not shown.
1
test/fixtures/sprites/outdoors.json
vendored
Normal file
1
test/fixtures/sprites/outdoors.json
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
test/fixtures/sprites/outdoors.png
vendored
Normal file
BIN
test/fixtures/sprites/outdoors.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
BIN
test/fixtures/styles/0.actual.png
vendored
Normal file
BIN
test/fixtures/styles/0.actual.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
BIN
test/fixtures/styles/0.expected.png
vendored
Normal file
BIN
test/fixtures/styles/0.expected.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
8
test/fixtures/styles/0.info.json
vendored
Normal file
8
test/fixtures/styles/0.info.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"zoom": 0,
|
||||
"latitude": 0,
|
||||
"longitude": 0,
|
||||
"angle": 0,
|
||||
"width": 512,
|
||||
"height": 512
|
||||
}
|
||||
34
test/fixtures/styles/0.style.json
vendored
Normal file
34
test/fixtures/styles/0.style.json
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "tiles/%d-%d-%d.vector.pbf",
|
||||
"tileSize": 512,
|
||||
"maxZoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"id": "background",
|
||||
"render": {
|
||||
"type": "background"
|
||||
},
|
||||
"style": {
|
||||
"background-color": "red"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "water",
|
||||
"source": "mapbox",
|
||||
"source-layer": "water",
|
||||
"render": {
|
||||
"type": "fill"
|
||||
},
|
||||
"style": {
|
||||
"fill-color": "blue",
|
||||
"fill-antialias": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
test/fixtures/styles/1.actual.png
vendored
Normal file
BIN
test/fixtures/styles/1.actual.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
test/fixtures/styles/1.expected.png
vendored
Normal file
BIN
test/fixtures/styles/1.expected.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
8
test/fixtures/styles/1.info.json
vendored
Normal file
8
test/fixtures/styles/1.info.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"zoom": 0,
|
||||
"latitude": 0,
|
||||
"longitude": 0,
|
||||
"angle": 0,
|
||||
"width": 512,
|
||||
"height": 512
|
||||
}
|
||||
33
test/fixtures/styles/1.style.json
vendored
Normal file
33
test/fixtures/styles/1.style.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "tiles/%d-%d-%d.vector.pbf",
|
||||
"tileSize": 512,
|
||||
"maxZoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"id": "background",
|
||||
"render": {
|
||||
"type": "background"
|
||||
},
|
||||
"style": {
|
||||
"background-color": "red"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "water",
|
||||
"source": "mapbox",
|
||||
"source-layer": "water",
|
||||
"render": {
|
||||
"type": "fill"
|
||||
},
|
||||
"style": {
|
||||
"fill-color": "blue"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
test/fixtures/tiles/0-0-0.vector.pbf
vendored
Normal file
BIN
test/fixtures/tiles/0-0-0.vector.pbf
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/tiles/2-1-1.vector.pbf
vendored
Normal file
BIN
test/fixtures/tiles/2-1-1.vector.pbf
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/tiles/2-1-2.vector.pbf
vendored
Normal file
BIN
test/fixtures/tiles/2-1-2.vector.pbf
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/tiles/2-2-1.vector.pbf
vendored
Normal file
BIN
test/fixtures/tiles/2-2-1.vector.pbf
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/tiles/2-2-2.vector.pbf
vendored
Normal file
BIN
test/fixtures/tiles/2-2-2.vector.pbf
vendored
Normal file
Binary file not shown.
@@ -3,18 +3,39 @@
|
||||
#include <llmr/map/map.hpp>
|
||||
#include <llmr/util/image.hpp>
|
||||
#include <llmr/util/io.hpp>
|
||||
#include <llmr/util/timer.hpp>
|
||||
#include <llmr/util/std.hpp>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
#include "../common/headless_view.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
const std::string base_directory = []{
|
||||
std::string fn = __FILE__;
|
||||
fn.erase(fn.find_last_of("/"));
|
||||
return fn;
|
||||
}();
|
||||
|
||||
TEST(Headless, initialize) {
|
||||
const int width = 1024;
|
||||
const int height = 768;
|
||||
class HeadlessTest : public ::testing::TestWithParam<const char *> {};
|
||||
|
||||
llmr::util::timer timer;
|
||||
TEST_P(HeadlessTest, render) {
|
||||
const char *base = GetParam();
|
||||
|
||||
const std::string style = llmr::util::read_file(base_directory + "/fixtures/styles/" + base + ".style.json");
|
||||
const std::string info = llmr::util::read_file(base_directory + "/fixtures/styles/" + base + ".info.json");
|
||||
const std::string expected_image = base_directory + "/fixtures/styles/" + base + ".expected.png";
|
||||
const std::string actual_image = base_directory + "/fixtures/styles/" + base + ".actual.png";
|
||||
|
||||
// Parse settings.
|
||||
rapidjson::Document doc;
|
||||
doc.Parse<0>((const char *const)info.c_str());
|
||||
ASSERT_EQ(false, doc.HasParseError());
|
||||
|
||||
const double zoom = doc.HasMember("zoom") ? doc["zoom"].GetDouble() : 0;
|
||||
const double angle = doc.HasMember("angle") ? doc["angle"].GetDouble() : 0;
|
||||
const double longitude = doc.HasMember("longitude") ? doc["longitude"].GetDouble() : 0;
|
||||
const double latitude = doc.HasMember("latitude") ? doc["latitude"].GetDouble() : 0;
|
||||
const unsigned int width = doc.HasMember("width") ? doc["width"].GetUint() : 0;
|
||||
const unsigned int height = doc.HasMember("height") ? doc["height"].GetUint() : 0;
|
||||
|
||||
// Setup OpenGL
|
||||
llmr::HeadlessView view;
|
||||
@@ -23,41 +44,27 @@ TEST(Headless, initialize) {
|
||||
view.resize(width, height);
|
||||
map.resize(width, height);
|
||||
|
||||
timer.report("map setup");
|
||||
map.setStyleJSON(style);
|
||||
|
||||
std::ifstream stylefile("./style.min.js");
|
||||
ASSERT_TRUE(stylefile.good());
|
||||
std::stringstream stylejson;
|
||||
stylejson << stylefile.rdbuf();
|
||||
|
||||
map.setStyleJSON(stylejson.str());
|
||||
|
||||
map.setLonLatZoom(0, 0, 2);
|
||||
map.setAngle(0);
|
||||
map.setLonLatZoom(longitude, latitude, zoom);
|
||||
map.setAngle(angle);
|
||||
map.setDebug(false);
|
||||
|
||||
timer.report("map style");
|
||||
|
||||
// Run the loop. It will terminate when we don't have any further listeners.
|
||||
map.run();
|
||||
|
||||
timer.report("map loop");
|
||||
const std::unique_ptr<uint32_t[]> pixels(new uint32_t[width * height]);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
|
||||
|
||||
uint32_t *pixels = new uint32_t[width * height];
|
||||
const std::string image = llmr::util::compress_png(width, height, pixels.get(), true);
|
||||
llmr::util::write_file(actual_image, image);
|
||||
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
timer.report("gl readpixels");
|
||||
|
||||
std::string result = llmr::util::compress_png(width, height, pixels, true);
|
||||
|
||||
timer.report("compress png");
|
||||
|
||||
llmr::util::write_file("out.png", result);
|
||||
|
||||
timer.report("save file");
|
||||
|
||||
delete[] pixels;
|
||||
|
||||
timer.report("destruct");
|
||||
const std::string expected_image_data(llmr::util::read_file(expected_image));
|
||||
const llmr::util::Image expected(expected_image_data, true);
|
||||
ASSERT_EQ(width, expected.getWidth());
|
||||
ASSERT_EQ(height, expected.getHeight());
|
||||
ASSERT_EQ(0, std::memcmp(pixels.get(), expected.getData(), width * height * 4));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Headless, HeadlessTest,
|
||||
::testing::Values("0", "1"));
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
'-framework OpenGL',
|
||||
],
|
||||
},
|
||||
'xcode_settings': {
|
||||
'OTHER_LDFLAGS': [
|
||||
'-framework OpenGL',
|
||||
],
|
||||
},
|
||||
}, {
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
@@ -161,16 +166,13 @@
|
||||
"./headless.cpp",
|
||||
"../common/headless_view.hpp",
|
||||
"../common/headless_view.cpp",
|
||||
"../common/curl_request.hpp",
|
||||
"../common/curl_request.cpp",
|
||||
"./fixtures/fixture_request.cpp",
|
||||
],
|
||||
"dependencies": [
|
||||
"../deps/gtest/gtest.gyp:gtest",
|
||||
"../llmr.gyp:llmr-x86",
|
||||
"link_gl",
|
||||
"link_curl",
|
||||
'../llmr.gyp:copy_default_stylesheet',
|
||||
'../llmr.gyp:copy_certificate_bundle',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
74
travis/travis-resources.template
Normal file
74
travis/travis-resources.template
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
{
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"Description": "mapbox-gl-native travis resources",
|
||||
"Resources": {
|
||||
"BuildUser": {
|
||||
"Type": "AWS::IAM::User",
|
||||
"Properties": {
|
||||
"Policies": [
|
||||
{
|
||||
"PolicyName": "list",
|
||||
"PolicyDocument": {
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::mapbox-gl-testing"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"PolicyName": "build",
|
||||
"PolicyDocument": {
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:DeleteObject",
|
||||
"s3:GetObject",
|
||||
"s3:GetObjectAcl",
|
||||
"s3:PutObject",
|
||||
"s3:PutObjectAcl"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::mapbox-gl-testing/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"BuildUserKey": {
|
||||
"Type": "AWS::IAM::AccessKey",
|
||||
"Properties": {
|
||||
"UserName": {
|
||||
"Ref": "BuildUser"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Outputs": {
|
||||
"AccessKeyId": {
|
||||
"Value": {
|
||||
"Ref": "BuildUserKey"
|
||||
}
|
||||
},
|
||||
"SecretAccessKey": {
|
||||
"Value": {
|
||||
"Fn::GetAtt": [
|
||||
"BuildUserKey",
|
||||
"SecretAccessKey"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user