utter 1.0.6 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +250 -8
- data/bin/console +6 -3
- data/bin/scaffold.rb +131 -0
- data/bin/templates/README.md +7 -0
- data/lib/internals/core/auth.rb +76 -0
- data/lib/internals/core/microservice.rb +39 -0
- data/lib/internals/core/service_discovery.rb +2 -0
- data/lib/internals/core/service_registration.rb +2 -0
- data/lib/{utter/model.rb → internals/testing/model_delete.rb} +1 -0
- data/lib/internals/testing/spec.rb +12 -0
- data/lib/utter.rb +61 -6
- data/samples/README.md +3 -0
- data/{examples → samples/upjoystream::v1::auth}/config.ru +2 -2
- data/{examples → samples/upjoystream::v1::auth/microservice/lib}/app.rb +2 -2
- data/samples/upjoystream::v1::torrents/Gemfile +4 -0
- data/samples/upjoystream::v1::torrents/Gemfile.lock +34 -0
- data/samples/upjoystream::v1::torrents/config.ru +17 -0
- data/samples/upjoystream::v1::torrents/domain/lib/echo_ext.rb +11 -0
- data/samples/upjoystream::v1::torrents/microservice/lib/app.rb +14 -0
- data/utter.gemspec +27 -7
- metadata +180 -14
- data/lib/utter/auth.rb +0 -74
- data/lib/utter/endpoint.rb +0 -27
- data/lib/utter/version.rb +0 -3
- /data/lib/{utter → internals/core}/store.rb +0 -0
- /data/{examples → samples/upjoystream::v1::auth}/Gemfile +0 -0
- /data/{examples → samples/upjoystream::v1::auth}/Gemfile.lock +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0200b470531e6b81be6eaaf1996ccf285d33a3b
|
4
|
+
data.tar.gz: 6f4925e7644d3125fb601e57624c04e34e006f68
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0cab0ac0c1a72a2e71a89fc810246a1c269a71327b0a0e2c814c49212a4880d5850cfe75d2b381b0a937287ca12f3677ccdc93443d569ec0b6904f8b2718d15
|
7
|
+
data.tar.gz: 09419fd90b9b0cb6c93424056274b15f20a056ad2b563477055a6d897bf65dc74936936fe9c960debe53b80b0c9e7d535069cf35e3374abc514e5ae6f0c1b226
|
data/README.md
CHANGED
@@ -1,19 +1,253 @@
|
|
1
|
-
Utter
|
2
|
-
|
1
|
+
What is Utter?
|
2
|
+
==============
|
3
|
+
Utter is a Domain-specific Microservices Framework written in Ruby for building both regular and advanced Rule-based web APIs.
|
4
|
+
|
5
|
+
|
6
|
+
What is a Domain-specific Microservice?
|
7
|
+
========================================
|
8
|
+
A domain is an area of knowledge such as an industry field or a subject of interest.
|
9
|
+
Building an application often requires the utilization of knowledge from a number of different domains.
|
10
|
+
|
11
|
+
Utter as a tool is used to manifest the implementation of an Application Model into a number of isolated domains, each refereed to as a `Domain-specific Microservice`.
|
12
|
+
|
13
|
+
A Domain-specific Microservice provides an isolation of a domain via defining its bounded context within a single service.
|
14
|
+
Such isolation supports the inhabitance of autonomous small teams.
|
15
|
+
|
16
|
+
Autonomous small teams are more capable of defining and hence understanding the problems involved within a bounded-context domain.
|
17
|
+
|
18
|
+
As business-inhereted intricate problems on domain basis it is easier to define domain basis as opposed to the much more difficult to define application-as-a-whole basis.
|
19
|
+
|
20
|
+
Each Utter Domain-specific Microservice incorporate its Domain-specific knowledge via extensions.
|
21
|
+
|
22
|
+
|
23
|
+
Utter is a - Simplicity Fuck'n Matters - microservies framework for building fun-sized independently deployable services.
|
24
|
+
|
25
|
+
Via using Utter each microservice, you create shall exhibit the following Domain-Driven Design coherences:
|
26
|
+
• Complete functionally Resource representation
|
27
|
+
• Append-only Data management
|
28
|
+
• Each microservice handles one resource (or verb), e.g Clients, Shop Items, Carts, Checkout, etc.
|
29
|
+
- minmizes the number of choices of Design Patterns per service.
|
30
|
+
|
31
|
+
fully acknowldges the philosphy of ... with the caveats of ...
|
32
|
+
|
33
|
+
- seperate reading data from writing data.
|
34
|
+
|
35
|
+
|
36
|
+
autonomous small teams, advocating complex pieces of logic should have , intricate
|
37
|
+
|
38
|
+
A Domain-specific Microservice is a declarative Rule-based web service, in the sense that allows a client to interact with it via a Domain-speific Ubiquitous Language(DDD) that changes the state of the system it represents.
|
39
|
+
|
40
|
+
In the same sense that natural langauges evolve while preserving its grammer rules, the Domain-specific Ubiquitious Language have a schema which acts as its grammer, or syntax if you may.
|
41
|
+
|
42
|
+
|
43
|
+
The format of the DUL is JSON, making it easily interchangable among different systems and the microservice components.
|
44
|
+
|
45
|
+
Example
|
46
|
+
#{events: [
|
47
|
+
#{facts: [
|
48
|
+
#{productions: [
|
49
|
+
#{production_rules: [
|
50
|
+
{rules: [
|
51
|
+
{subject: {name: "3am abdo", type: "souq"}, predicat: {action: "wants"}, object: {service: "delivery", type: "cup of tea", quantity: "1" }},
|
52
|
+
{subject: {name: "ss", age: "11"}, predicat: {action: kill, method: car accident}, object: {name: "john", age: "33"}},
|
53
|
+
{subject: {name: "ss", age: "11"}, predicat: {action: kill, method: car accident}, object: {name: "john", age: "33"}},
|
54
|
+
{subject: {name: "ss", age: "11"}, predicat: {action: kill, method: car accident}, object: {name: "john", age: "33"}}
|
55
|
+
]}
|
56
|
+
|
57
|
+
#Declarative microservice means that events changing the state of the system are domain-specific yet indepentant from the technologies(languages\libraries\frameworks) used to implement the microservice. A level of abstraction for interfacing with the domain and not with the implmention technologies.
|
58
|
+
|
59
|
+
|
60
|
+
#Utter define a 'Declarative API' as an API that consists of a number of microservices, that takes a JSON payload of "events" form an API client that declares what the system should do (as opposed to how it should do it) and the backend of the API carries the exact same results regardless of the techinical details (implmentation language (ruby, python, etc.) or frameworks used).
|
61
|
+
|
62
|
+
|
63
|
+
Rules allow us to represent certain kinds of knowledge that are difficult to employ a conventional procedural program.
|
64
|
+
Rule-based programs also separate the knowledge from the rest of the program in such a way that a change in the knowledge base is not propagated throughout the program like a change in a procedural program can be.
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
What's Utter Main UseCase?
|
69
|
+
===========================
|
70
|
+
WRITING EFFECTIVE USE CASES: http://alistair.cockburn.us/get/2465
|
71
|
+
|
72
|
+
Problem:
|
73
|
+
|
74
|
+
Solution:
|
75
|
+
"The programmer should understand what he is doing, that his growing product remains firmly within his intellectual grip" - Dijkstra
|
76
|
+
|
77
|
+
Utter offers you the gift of simplicity via an architectural agility that you get from building simple (one fold,), easy(a very near mental leap) microservices;
|
78
|
+
this dominates all other kinds of agility. Good design is about seperating things apart, in the sense that "less is more".
|
79
|
+
|
80
|
+
Utter helps you divide up your software project into fun-sized independently deployable microservices.
|
81
|
+
|
82
|
+
Utter lets you build fun-sized independently deployable API endpoints.
|
83
|
+
|
84
|
+
Reusability\Usability
|
85
|
+
====================
|
86
|
+
each utter scopes down its microservice be domain-specific, making it fun-sized codebase. that each domain framework used-by\created-for the microservice can be extended via plugins and reused declarativly in another microservice of the same domain.
|
87
|
+
|
88
|
+
Mapping a single domain into many mircroservices. but one microservice to focus on one aspect of the domain and customize its domain stack via extneded middlewares.
|
89
|
+
|
90
|
+
Encapsulating functinality is not a new idea, but what makes utter stands out is that the developed codebase now is not only reusable, but actually Usable from the prespective of other microservice developers, as they access the functionality declarativly, without worrying about the implmentation details.
|
91
|
+
|
92
|
+
Utter Middleware extensiable architecture makes every compnenet reusable. and Declarative programming makes every component created via Utter highly usable.
|
93
|
+
|
94
|
+
|
95
|
+
What is the Domain-specific Microservices Architectural Pattern?
|
96
|
+
============================================================
|
97
|
+
An architectural pattern is a general, reusable solution to a commonly occurring problem in software architecture within a given context.[1] Architectural patterns are similar to software design pattern but have a broader scope. The architectural patterns address various issues in software engineering, such as computer hardware performance limitations, high availability and minimization of a business risk. Some architectural patterns have been implemented within software frameworks.
|
98
|
+
|
99
|
+
When developing a software architecture, we have to consider not only functional requirements, but also non-functional requirements, such as performance, robustness, failure tolerance, throughput, adaptability, extendibility, reusability, and so on. Indeed, one of the purposes of software architectures is to be able to quickly tell how a piece of software satisfies its requirements.
|
100
|
+
|
101
|
+
|
102
|
+
What is a Domains-specific Microservice?
|
103
|
+
==================================================
|
104
|
+
A Domain-specific Mircoservice is a web service responsible to utilize the knowledge of a specific domain.
|
105
|
+
|
106
|
+
How to define the scope of a domain?
|
107
|
+
======================================
|
108
|
+
Domain scoping is the process that dentifies the domain of interest, the stakeholders and their goals.
|
109
|
+
Domain scoping is economically viable and promises success.
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
When to extend a domain vs dividing it up into an n number of finer-grained scoped domains?
|
114
|
+
=============================================================================================
|
115
|
+
Knowledge utilized within an Domain-specific Microservice should only belong to its core domain. If the case arises that supporting domains or other generic domains are identifable, then they should be scoped out into their own domains.
|
116
|
+
|
117
|
+
How to extend a domain?
|
118
|
+
=======================
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
What does Utter consits of under the hood?
|
123
|
+
==========================================
|
124
|
+
Sinatra
|
125
|
+
Mushin
|
126
|
+
SSD
|
127
|
+
DiskCloud
|
128
|
+
|
129
|
+
What is mushin?
|
130
|
+
===============
|
131
|
+
Building an application often requires the utilization of knowledge from a number of different domains.
|
132
|
+
Domainspecific frameworks are source code artifacts, rather limited to mainstream domains such as web, desktop, and mobile development;
|
133
|
+
and they incorporate knowledge from other domains, via extensions.
|
134
|
+
Mushin argues that a diversity of domainspecific frameworks might positively influence the construction of software applications.
|
135
|
+
Hence Mushin intends to support domainspecific framework developers, via providing a generative approach for building domainspecific frameworks,
|
136
|
+
Hoping that this may aid the convergence towards a diversity of domainspecific frameworks and their corresponding ecosystems.
|
137
|
+
|
138
|
+
Utter is a - Simplicity Fuck'n Matters - microservies framework for building fun-sized independently deployable services.
|
139
|
+
|
140
|
+
Via using Utter each microservice, you create shall exhibit the following Domain-Driven Design coherences:
|
141
|
+
• Complete functionally Resource representation
|
142
|
+
• Append-only Data management
|
143
|
+
• Each microservice handles one resource (or verb), e.g Clients, Shop Items, Carts, Checkout, etc.
|
144
|
+
- minmizes the number of choices of Design Patterns per service.
|
145
|
+
|
146
|
+
fully acknowldges the philosphy of ... with the caveats of ...
|
147
|
+
|
148
|
+
- seperate reading data from writing data.
|
149
|
+
|
150
|
+
Independant
|
151
|
+
=============
|
152
|
+
- Independent Hires\Outsourcing
|
153
|
+
By dividing up your system into Utter services you can safely hire\outsource outsource development for some functionality without the need for them to ever touch your codebase, Simply all they need is the documentation of the APIs they are to interact with.
|
154
|
+
|
155
|
+
- Independent Deployability is key
|
156
|
+
It enables separation and independent evolution of
|
157
|
+
• code base
|
158
|
+
• technology stacks
|
159
|
+
• scaling
|
160
|
+
• and features, too
|
161
|
+
|
162
|
+
- Independent code base
|
163
|
+
Each service has its own software repository
|
164
|
+
• Codebase is maintainable for developers – it fits into their brain
|
165
|
+
• Tools work fast – building, testing, refactoring code takes seconds
|
166
|
+
• Service startup only takes seconds
|
167
|
+
• No accidental cross-dependencies between code bases
|
168
|
+
|
169
|
+
- Independent technology stacks
|
170
|
+
Each service is implemented on its own technology stacks
|
171
|
+
• The technology stack can be selected to fit the task best
|
172
|
+
• Teams can also experiment with new technologies within a single microservice
|
173
|
+
• No system-wide standardized technology stack also means
|
174
|
+
• No struggle to get your technology introduced to the canon
|
175
|
+
• No piggy-pack dependencies to unnecessary technologies or libraries
|
176
|
+
• It‘s only your own dependency hell you need to struggle with
|
177
|
+
• Selected technology stacks are often very lightweight
|
178
|
+
• A microservice is often just a single process that is started via command line, and not code and
|
179
|
+
configuration that is deployed to a container.
|
180
|
+
|
181
|
+
- Independent Scaling
|
182
|
+
Each microservice can be scaled independently.
|
183
|
+
Identified bottlenecks can be addressed directly.
|
184
|
+
Data sharding can be applied to microservices as needed (Utter uses DiskCloud).
|
185
|
+
Parts of the system that do not represent bottlenecks can remain simple and un-scaled.
|
186
|
+
|
187
|
+
- Independent evolution of Features:
|
188
|
+
Microservices can be extended without affecting other services,
|
189
|
+
For example, you can deploy a new version of (a part of) the UI without re-deploying the whole systemi,
|
190
|
+
You can also go so far as to replace the service by a complete rewrite. But you have to ensure that the service interface remains stable
|
191
|
+
|
192
|
+
|
193
|
+
|
194
|
+
ref: http://www.pst.ifi.lmu.de/Lehre/wise-14-15/mse/microservice-architectures.pdf
|
195
|
+
|
196
|
+
|
197
|
+
What is Utter?
|
198
|
+
==============
|
199
|
+
- An utter microservice is an endpoint (a web delivery mechanism) on top of a single domain-based bounded context (mushin domain along with plugins).
|
200
|
+
- Each utter application is a dockerized straightforward-to-test isolated "SINGLE" versioned independently-deployable Endpoint(with an n number of routes) along with a domain bounded-context.
|
201
|
+
- your API documentation acts as the registery of which each team member knows what services are available on which endpoinnds and versions.
|
202
|
+
- you build an endpoint service, you deploy it indepentently, you update the centerilized API docs. and the rest of your team and the world get to start using it.
|
203
|
+
- utter gives you fine-tuning for which part of your application needs horizontal scale resources, as your application is really divided up into microserices.
|
204
|
+
- utter builds endpoints that logs out with 'Correlation IDs' that helps you to stacktrace errors and visualize how services talk to each other.
|
205
|
+
- normally the term “micro” refers to the sizing: a microservice must be manageable by a single development team (5-9
|
206
|
+
developers), Utter argues that a service is a single endpoint/single domain (usually managed by a pair of software engineers). Utter belives that this enforced constrain makes you scale down your domain and its endpoint interfaces small enough but not too small.
|
207
|
+
- Independent deployability implies no shared state and inter-process communication (often via HTTP REST-ish
|
208
|
+
interfaces)
|
209
|
+
- Functional system decomposition means vertical slicing
|
210
|
+
(in contrast to horizontal slicing through layers)
|
211
|
+
- Microservices are fun-sized services, as in
|
212
|
+
“still fun to develop and deploy”
|
3
213
|
|
4
|
-
Utter is microservies framework for building independently deployable services.
|
5
214
|
|
6
215
|
Why Utter
|
7
216
|
==========
|
8
217
|
Utter loves sinatra! thats why it is built on top of it, but make smart descions to faciliate the building of microservices.
|
218
|
+
Utter doesn't GIVE A RAT ASS about SQL-based backends integrations (IF YOUR OLD SQL TROLLS AREN't DEAD ALREADY, FIRE'M ALL).
|
9
219
|
|
10
220
|
Alternative Frameworks
|
11
221
|
=======================
|
12
222
|
Utter sees Grape as poluted framework.
|
13
|
-
Utter sees Rails as MUST-Avoid framework.
|
223
|
+
Utter sees Rails as an ALMOST-ALWAYS A MUST-Avoid framework.
|
224
|
+
Utter sees the Lotus as NOT focused enough on microservices.
|
225
|
+
Utter sees Padrino as Rails wanna-be that provides TOO MANY options! (not microservices specific)
|
226
|
+
Utter sees Ramaze, NYNY, Nancy, Cuba, Camping, Crepe, Hobbit, Kenji, Brooklyn as absoulte yet a GOTO to steal some good ideas!
|
227
|
+
As simplicity is a Prequesite for Reliability, IT FUCK'N MATTERS!
|
228
|
+
|
229
|
+
Utter Project Structure
|
230
|
+
=========================
|
231
|
+
- ProjectName::V1::MicroserviceName (`utter new project` asks you about projectname, version, endpoint name i.e gitlapse::v1::lapses)
|
232
|
+
- microservice (a microservice web delivery mechanism (interface) of the application Domain bounded context) - NOTE it is "endpoint" and NOT "endpoints"
|
233
|
+
- lib
|
234
|
+
- lapses_microservice.rb
|
235
|
+
- spec
|
236
|
+
- lapses_microservice_spec.rb
|
237
|
+
- domain (a mushin domain framework, along with its middlewares - thats the lib and spec of your application) - NOTE it is "domain" and NOT "domains"
|
238
|
+
- lib
|
239
|
+
- lapse.rb (uses mushin framework stack)
|
240
|
+
- middleware_name.rb (middleware plugin)
|
241
|
+
- middleware_name.rb (middleware plugin)
|
242
|
+
- spec
|
243
|
+
- lapses_spec.rb
|
244
|
+
- Dockerfile
|
245
|
+
- Gemfile
|
246
|
+
- Rakefile (for running domain and endpoint tests) (rake is also used for building, and running dockerfile as subtitute for my run.sh)
|
14
247
|
|
15
|
-
|
16
|
-
|
248
|
+
Utter Examples
|
249
|
+
===============
|
250
|
+
Example: ========
|
17
251
|
> utter deploy user@serverip
|
18
252
|
1. Uses puma and nginx Dockerfile to create a proxy container and bind it to the host server
|
19
253
|
2. this command makes a packages gem with the following structure for each endpoint and uploads it to the server
|
@@ -70,10 +304,18 @@ Example:
|
|
70
304
|
====================
|
71
305
|
- Utter deploy command deploys for each endpoint (endpoint gem + Dockerfile, DATA docker-volume for SSD), nginx image for mapping ports and services.
|
72
306
|
|
73
|
-
|
74
|
-
|
75
307
|
External Refs:
|
76
308
|
- http://martinfowler.com/articles/microservices.html
|
77
309
|
- http://highscalability.com/blog/2014/4/8/microservices-not-a-free-lunch.html
|
78
310
|
|
311
|
+
What is a Rule-based Microservice (Advanced)
|
312
|
+
=============================================
|
313
|
+
A rule-based microservice is a service that allows you to send a set of production-rules(facts) that describe what you like the status of your application to be.
|
314
|
+
In oppostion a normal microservice would ask you to send primative data which you would normall catch on the backend and mainpulate somehow to make it ready suitable to change the state of your application.
|
315
|
+
|
316
|
+
In that sense rule-based microservice allows its clients to interact with it via a "Rule Book". clients read the "Rule Book" and send facts to the microservice, the microservice checks the "Rule book" and updates the status of the application accordingly. And as the microservice is domain-specific so is the Rule Book, meaning the clients can always get an Expert's advice on what the status of the application should be. This makes the Microservice highly usable!
|
317
|
+
|
318
|
+
More info is always found on hackspree videos or blogposts at hackspree.com; videos and blogposts are part of active hackspree online workshops to which users can register to fully if they like. Also other contributors who provide consulting services for Utter, Mushin, etc. can edit this wikipage on github to add their corrsponding references as well, by no means this is exclusive to hackspree.
|
79
319
|
|
320
|
+
https://www.hackspree.com/microservices-course/whatismicroservices.video
|
321
|
+
https://www.hackspree.com/ChainofResponsibilityDesignPattern
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
|
-
require "utter"
|
4
|
+
#require "utter"
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,8 @@ require "utter"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|
13
|
+
#require "irb"
|
14
|
+
#IRB.start
|
15
|
+
require 'pry'
|
16
|
+
|
17
|
+
Pry.start
|
data/bin/scaffold.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
#TODO remove highline and use Thor generators
|
2
|
+
# http://whatisthor.com/
|
3
|
+
# http://blog.plataformatec.com.br/2009/07/creating-your-own-generators-with-thor/
|
4
|
+
|
5
|
+
require 'highline'
|
6
|
+
# Basic usage
|
7
|
+
|
8
|
+
cli = HighLine.new
|
9
|
+
|
10
|
+
|
11
|
+
# project name
|
12
|
+
answer = cli.ask "What's your project name?"
|
13
|
+
puts "You have answered: #{answer}"
|
14
|
+
|
15
|
+
# microservice version
|
16
|
+
answer = cli.ask "What's your microservice version?"
|
17
|
+
puts "You have answered: #{answer}"
|
18
|
+
|
19
|
+
|
20
|
+
cli.choose do |menu|
|
21
|
+
menu.prompt = "What's your miroservice version?"
|
22
|
+
menu.choice(:v1) do
|
23
|
+
cli.say("confirmed v1")
|
24
|
+
end
|
25
|
+
|
26
|
+
menu.choices(:v2) do
|
27
|
+
cli.say("confirmed v2")
|
28
|
+
end
|
29
|
+
|
30
|
+
menu.choices(:v3) do
|
31
|
+
cli.say("confirmed v3")
|
32
|
+
end
|
33
|
+
|
34
|
+
menu.choices(:v4) do
|
35
|
+
cli.say("confirmed v4")
|
36
|
+
end
|
37
|
+
|
38
|
+
menu.choices(:v5) do
|
39
|
+
cli.say("confirmed v5")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
# microservice version
|
47
|
+
answer = cli.ask "What's your microservice name?"
|
48
|
+
puts "You have answered: #{answer}"
|
49
|
+
|
50
|
+
# microservice type
|
51
|
+
#answer = cli.ask "Is your microservice public or private?"
|
52
|
+
#puts "You have answered: #{answer}"
|
53
|
+
|
54
|
+
|
55
|
+
cli.choose do |menu|
|
56
|
+
menu.prompt = "What's your miroservice type?"
|
57
|
+
menu.choice(:public) do
|
58
|
+
cli.say("confirmed 'Public' microservice!")
|
59
|
+
end
|
60
|
+
menu.choices(:private) do
|
61
|
+
cli.say("confirmed 'Private' microservice!")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
# microservice deployment
|
68
|
+
#answer = cli.ask "What's your microservice host IP?"
|
69
|
+
#puts "You have answered: #{answer}"
|
70
|
+
#cli.ask("Enter your host password: ") { |q| q.echo = "x" }
|
71
|
+
|
72
|
+
#cli.choose do |menu|
|
73
|
+
# menu.prompt = "Please choose your favorite programming language? "
|
74
|
+
# menu.choice(:ruby) { cli.say("Good choice!") }
|
75
|
+
# menu.choices(:python, :perl) { cli.say("Not from around here, are you?") }
|
76
|
+
#end
|
77
|
+
|
78
|
+
|
79
|
+
=begin
|
80
|
+
|
81
|
+
# Default answer
|
82
|
+
|
83
|
+
cli.ask("Company? ") { |q| q.default = "none" }
|
84
|
+
|
85
|
+
|
86
|
+
# Validation
|
87
|
+
|
88
|
+
cli.ask("Age? ", Integer) { |q| q.in = 0..105 }
|
89
|
+
cli.ask("Name? (last, first) ") { |q| q.validate = /\A\w+, ?\w+\Z/ }
|
90
|
+
|
91
|
+
|
92
|
+
# Type conversion for answers:
|
93
|
+
|
94
|
+
cli.ask("Birthday? ", Date)
|
95
|
+
cli.ask("Interests? (comma sep list) ", lambda { |str| str.split(/,\s*/) })
|
96
|
+
|
97
|
+
|
98
|
+
# Reading passwords:
|
99
|
+
|
100
|
+
cli.ask("Enter your password: ") { |q| q.echo = false }
|
101
|
+
cli.ask("Enter your password: ") { |q| q.echo = "x" }
|
102
|
+
|
103
|
+
|
104
|
+
# ERb based output (with HighLine's ANSI color tools):
|
105
|
+
cli.say("This should be <%= color('bold', BOLD) %>!")
|
106
|
+
|
107
|
+
|
108
|
+
# Menus:
|
109
|
+
|
110
|
+
cli.choose do |menu|
|
111
|
+
menu.prompt = "Please choose your favorite programming language? "
|
112
|
+
menu.choice(:ruby) { cli.say("Good choice!") }
|
113
|
+
menu.choices(:python, :perl) { cli.say("Not from around here, are you?") }
|
114
|
+
menu.default = :ruby
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
## Using colored indices on Menus
|
119
|
+
|
120
|
+
#HighLine::Menu.index_color = :rgb_77bbff # set default index color
|
121
|
+
|
122
|
+
cli.choose do |menu|
|
123
|
+
# menu.index_color = :rgb_999999 # override default color of index
|
124
|
+
# you can also use constants like :blue
|
125
|
+
menu.prompt = "Please choose your favorite programming language? "
|
126
|
+
menu.choice(:ruby) { cli.say("Good choice!") }
|
127
|
+
menu.choices(:python, :perl) { cli.say("Not from around here, are you?") }
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
=end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
This directory contains common microservice templates
|
2
|
+
- auth microservice template
|
3
|
+
- logging microservice template
|
4
|
+
- admin microservice template
|
5
|
+
|
6
|
+
- User generate a template and specifiy certain attr to customize the template to their own needs.
|
7
|
+
- User then use/further developm the generated microservice.
|
@@ -0,0 +1,76 @@
|
|
1
|
+
=begin
|
2
|
+
#TODO write RDoc
|
3
|
+
module Utter
|
4
|
+
module Internals
|
5
|
+
class Auth < Rack::Auth::Basic #TODO digest is better than basic?
|
6
|
+
def call(env)
|
7
|
+
request = Rack::Request.new(env)
|
8
|
+
|
9
|
+
case request.path when '/docs'
|
10
|
+
@app.call(env) # skip auth to access documentation
|
11
|
+
else
|
12
|
+
super # perform auth
|
13
|
+
#TODO use json "sinatra/json" here to ensure all outcoming response are in json
|
14
|
+
|
15
|
+
#res = Rack::Response.new
|
16
|
+
|
17
|
+
# This will automatically set the Content-Length header for you
|
18
|
+
##res.write "Hello from Rack!"
|
19
|
+
|
20
|
+
# You can get/set headers with square bracket syntax:
|
21
|
+
##res["Content-Type"] = "Content-type: application/json; charset=utf-8"
|
22
|
+
|
23
|
+
# returns the standard [status, headers, body] array
|
24
|
+
##res.finish
|
25
|
+
|
26
|
+
# You can set and delete cookies
|
27
|
+
# res.set_cookie("user_id", 1)
|
28
|
+
# res.delete_cookie("user_id"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Any class that inherits from Endpoint, may include Utter::Token to add security
|
34
|
+
# token, a token can be used for authenticating a signed-in user or as an API for your system.
|
35
|
+
#
|
36
|
+
# Usage
|
37
|
+
#
|
38
|
+
# via curl https://api.example.com/v1/endpoint_name -u token_value:
|
39
|
+
# via Browser http://token_value@localhost:4567/
|
40
|
+
# If you need to authenticate via bearer auth (e.g., for a cross-origin request), use -H "Authorization: Bearer #{token_value}" instead of -u token_value:
|
41
|
+
#
|
42
|
+
# More Info
|
43
|
+
# - https://en.wikipedia.org/wiki/Digest_access_authentication
|
44
|
+
# - https://github.com/rack/rack/blob/master/lib/rack/auth/basic.rb
|
45
|
+
module Secured
|
46
|
+
def self.included(base)
|
47
|
+
base.class_eval do
|
48
|
+
|
49
|
+
use Auth, "#{self}" do |username, password|
|
50
|
+
|
51
|
+
$log.info "username #{username}, password #{username}"
|
52
|
+
|
53
|
+
if !username.nil? && !password.nil? then
|
54
|
+
if !User.ssd(username).nil? then
|
55
|
+
if password == User.ssd(username).password then
|
56
|
+
true # Access Granted
|
57
|
+
else
|
58
|
+
false # Access Denied
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# 404 Error!
|
65
|
+
not_found do
|
66
|
+
status 404
|
67
|
+
"404 - Check #{self} API documentation"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
=end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#TODO write RDoc
|
2
|
+
require 'fileutils'
|
3
|
+
require 'sinatra'
|
4
|
+
require "sinatra/json"
|
5
|
+
require 'securerandom'
|
6
|
+
require 'sinatra/cross_origin'
|
7
|
+
require 'net/http' # Net::HTTP.get('example.com', '/index.html') # => String
|
8
|
+
|
9
|
+
module Utter
|
10
|
+
module Internals
|
11
|
+
|
12
|
+
class Microservice < Sinatra::Base
|
13
|
+
# if cross_origin is required\loaded then make register Sinatra::CrossOrigin
|
14
|
+
# And
|
15
|
+
#register Sinatra::CrossOrigin
|
16
|
+
|
17
|
+
#TODO set a flag to disable this in production for security
|
18
|
+
# this helps testing APIs on localmachines as CORS fucks developers time.
|
19
|
+
# But not recommended to be set while in production enviroments
|
20
|
+
before do
|
21
|
+
response.headers["Access-Control-Allow-Origin"] = "*"
|
22
|
+
response.headers["Access-Control-Allow-Methods"] = "POST"
|
23
|
+
p response.headers.inspect
|
24
|
+
end
|
25
|
+
|
26
|
+
configure { set :server, :puma }
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
#class Public::Microservice < Utter::Microservice; end
|
31
|
+
|
32
|
+
#class Private::Microservice < Utter::Microservice
|
33
|
+
#TODO do somthing here to make it secure via some mechanism!
|
34
|
+
# as we don't do websites, we striclty focus on APIs we can use HTTP basic auth to make it secure!?
|
35
|
+
|
36
|
+
#end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/utter.rb
CHANGED
@@ -1,13 +1,68 @@
|
|
1
1
|
require 'logger'
|
2
|
+
require 'mushin'
|
2
3
|
|
3
|
-
require_relative "
|
4
|
-
require_relative "
|
5
|
-
require_relative "
|
6
|
-
require_relative "utter/endpoint"
|
7
|
-
require_relative "utter/auth"
|
8
|
-
|
4
|
+
#require_relative "internals/core/store"
|
5
|
+
#require_relative "internals/core/auth"
|
6
|
+
require_relative "internals/core/microservice"
|
9
7
|
|
10
8
|
|
9
|
+
# Utter defines its interfacing points here. Utter communicate seamlessly
|
10
|
+
# via this facade pattern to its internals. This allows all Utter applications
|
11
|
+
# makes it easy to have consistant improvments without updating their codebases.
|
12
|
+
#
|
13
|
+
#NOTE According to Semantic Versioning 2.0.0 (http://semver.org/); Any changes
|
14
|
+
# to this file would require an upgrade to a new Major version.
|
11
15
|
module Utter
|
16
|
+
# MAJOR version when you make incompatible API changes,
|
17
|
+
# MINOR version when you add functionality in a backwards-compatible manner, and
|
18
|
+
# PATCH version when you make backwards-compatible bug fixes.
|
19
|
+
VERSION = "1.0.9"
|
20
|
+
|
12
21
|
$log = Logger.new(STDOUT)
|
22
|
+
|
23
|
+
# Utter choose to provide its functionality via Classes vs Modules as an assertive way of specifing behaviour.
|
24
|
+
|
25
|
+
# Auth is used to build authentication Microservices and is also used utter generated templates.
|
26
|
+
#class Auth < Utter::Internals::Auth; end
|
27
|
+
|
28
|
+
# BASIC FEATURE
|
29
|
+
#TODO configuring an options {} to define if a microservice is public or private
|
30
|
+
# Public::Microservice can be used to provide a microservice that doesn't require authentication.
|
31
|
+
#class Public::Microservice < Utter::Internals::Public::Microservice; end
|
32
|
+
# Private::Microservice can be used to provide a microservice that DOES require authentication.
|
33
|
+
class Microservice < Utter::Internals::Microservice; end
|
34
|
+
|
35
|
+
# BASIC FEATURE
|
36
|
+
# Usage of non domain-specific stack inside a microservice would be like
|
37
|
+
# Stack.new do
|
38
|
+
# use Trace, "A opts hash", x
|
39
|
+
# use Trace, "B opts hash", "B params hash"
|
40
|
+
# use Trace, "C opts hash", "C params hash"
|
41
|
+
# end
|
42
|
+
# Very helpful if you just want to build extenstions conforming to Mushin ducking interface of :initialize(app), :call(env)
|
43
|
+
# Yet it is strongly encourged to require your own domain-specific frameworks generated via mushin inexample, and use only
|
44
|
+
# a constraining yourself for a single domain-framework per microservice. example
|
45
|
+
#
|
46
|
+
# require 'domainframeworkXYZ'
|
47
|
+
# require 'domainframeworkXYZ_ext_1'
|
48
|
+
# require 'domainframeworkXYZ_ext_2'
|
49
|
+
# require 'domainframeworkXYZ_ext_3'
|
50
|
+
# DomainFrameworkXYZ::Stack do
|
51
|
+
# use DomainFrameworkXYZ_EXT_1, opts, params
|
52
|
+
# use DomainFrameworkXYZ_EXT_2, opts, params
|
53
|
+
# use DomainFrameworkXYZ_EXT_3, opts, params
|
54
|
+
# end
|
55
|
+
# this way your work on that domain is ackonwledge\enhanced by the community at large.
|
56
|
+
class Stack < Mushin::Stack
|
57
|
+
# Manipulating the Stack
|
58
|
+
# Implicitly insert storage via SSD ext (NOONE ELSE NEEDS TO KNOW ABOUT SSD, EXCEPT HERE! BEAUTIFUL!!!!!!)
|
59
|
+
# or Explicitly insert it while being in the microservice this way develoeprs get to choose when to use
|
60
|
+
# the right tool for the job. Example SSD for somthing, and Redis for some Caching microservice, etc.
|
61
|
+
end
|
62
|
+
|
63
|
+
# ADVANCED FEATURE
|
64
|
+
#TODO expose mushin rule-based capabilities via Utter to provide json rule-based microservices
|
65
|
+
|
66
|
+
# Asserts that Utter::Internals namespace is inaccessible directly for Utter apps.
|
67
|
+
private_constant :Internals
|
13
68
|
end
|
data/samples/README.md
ADDED
@@ -3,7 +3,7 @@ require 'utter'
|
|
3
3
|
|
4
4
|
module API
|
5
5
|
module V1
|
6
|
-
class PublicEndpoint < Utter::Endpoint
|
6
|
+
class PublicEndpoint < Utter::Public::Endpoint
|
7
7
|
$log.info("mounting #{self}")
|
8
8
|
get '/' do
|
9
9
|
"public info"
|
@@ -11,7 +11,7 @@ module API
|
|
11
11
|
run! if app_file == $0
|
12
12
|
end
|
13
13
|
|
14
|
-
class PrivateEndpoint < Utter::Endpoint
|
14
|
+
class PrivateEndpoint < Utter::Private::Endpoint
|
15
15
|
$log.info("mounting #{self}")
|
16
16
|
get '/' do
|
17
17
|
"private info (eyes only)"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
multi_json (1.12.1)
|
5
|
+
rack (1.6.4)
|
6
|
+
rack-protection (1.5.3)
|
7
|
+
rack
|
8
|
+
sinatra (1.4.7)
|
9
|
+
rack (~> 1.5)
|
10
|
+
rack-protection (~> 1.4)
|
11
|
+
tilt (>= 1.3, < 3)
|
12
|
+
sinatra-cross_origin (0.3.2)
|
13
|
+
sinatra-json (0.1.0)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
sinatra (~> 1.0)
|
16
|
+
ssd (0.1.4)
|
17
|
+
tilt (2.0.5)
|
18
|
+
utter (1.0.5)
|
19
|
+
sinatra
|
20
|
+
sinatra-cross_origin
|
21
|
+
sinatra-json
|
22
|
+
ssd
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
utter
|
29
|
+
|
30
|
+
RUBY VERSION
|
31
|
+
ruby 2.3.1p112
|
32
|
+
|
33
|
+
BUNDLED WITH
|
34
|
+
1.12.5
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# config.ru (run with rackup)
|
2
|
+
##begin
|
3
|
+
# require 'rack/show_exceptions'
|
4
|
+
#rescue LoadError
|
5
|
+
# require 'rack/showexceptions'
|
6
|
+
#end
|
7
|
+
require 'bundler/setup'
|
8
|
+
Bundler.require(:default)
|
9
|
+
|
10
|
+
require 'utter'
|
11
|
+
#require './app'
|
12
|
+
Dir[File.dirname(__FILE__) + 'domain/lib/*.rb'].each {|file| require file }
|
13
|
+
Dir[File.dirname(__FILE__) + 'microservice/lib/*.rb'].each {|file| require file }
|
14
|
+
|
15
|
+
map('/') do
|
16
|
+
run API::V1::Torrents
|
17
|
+
end
|
data/utter.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
|
4
|
+
require_relative 'lib/utter'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "utter"
|
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["zotherstupidguy"]
|
10
10
|
spec.email = ["zotherstupidguy@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{Utter is
|
13
|
-
|
12
|
+
spec.summary = %q{Utter is a Domain-specific Microservices Framework written in Ruby.}
|
13
|
+
spec.description = %q{ Utter is a Domain-specific Microservices Framework written in Ruby. Utter helps you divide up your software project into fun-sized independently deployable API endpoints.}
|
14
14
|
spec.homepage = "https://github.com/utter-rb"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -27,9 +27,22 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
+
spec.add_development_dependency "pry"
|
31
|
+
spec.add_runtime_dependency "pry"
|
32
|
+
|
33
|
+
spec.add_development_dependency "highline"
|
34
|
+
spec.add_runtime_dependency "highline"
|
35
|
+
|
36
|
+
|
30
37
|
spec.add_development_dependency "bundler", "~> 1.12"
|
38
|
+
spec.add_runtime_dependency "bundler", "~> 1.12" #TODO use bundler to generate customized Gemfile for Utter generated files
|
39
|
+
|
31
40
|
spec.add_development_dependency "rake", "~> 10.0"
|
41
|
+
spec.add_runtime_dependency "rake", "~> 10.0"
|
42
|
+
|
32
43
|
spec.add_development_dependency "minitest", "~> 5.0"
|
44
|
+
spec.add_runtime_dependency "minitest", "~> 5.0"
|
45
|
+
|
33
46
|
|
34
47
|
spec.add_development_dependency "sinatra"
|
35
48
|
spec.add_runtime_dependency 'sinatra'
|
@@ -40,10 +53,17 @@ Gem::Specification.new do |spec|
|
|
40
53
|
spec.add_development_dependency "sinatra-cross_origin"
|
41
54
|
spec.add_runtime_dependency "sinatra-cross_origin"
|
42
55
|
|
43
|
-
spec.add_development_dependency "ssd"
|
44
|
-
spec.add_runtime_dependency "ssd"
|
56
|
+
spec.add_development_dependency "ssd"
|
57
|
+
spec.add_runtime_dependency "ssd"
|
58
|
+
|
59
|
+
spec.add_development_dependency "rack-test"
|
60
|
+
spec.add_runtime_dependency "rack-test"
|
61
|
+
|
62
|
+
|
63
|
+
spec.add_development_dependency "puma"
|
64
|
+
spec.add_runtime_dependency "puma"
|
45
65
|
|
46
|
-
spec.add_development_dependency "
|
47
|
-
spec.add_runtime_dependency "
|
66
|
+
spec.add_development_dependency "mushin"
|
67
|
+
spec.add_runtime_dependency "mushin"
|
48
68
|
|
49
69
|
end
|
metadata
CHANGED
@@ -1,15 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: utter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zotherstupidguy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: highline
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: highline
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
13
69
|
- !ruby/object:Gem::Dependency
|
14
70
|
name: bundler
|
15
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +80,20 @@ dependencies:
|
|
24
80
|
- - "~>"
|
25
81
|
- !ruby/object:Gem::Version
|
26
82
|
version: '1.12'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.12'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.12'
|
27
97
|
- !ruby/object:Gem::Dependency
|
28
98
|
name: rake
|
29
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +108,20 @@ dependencies:
|
|
38
108
|
- - "~>"
|
39
109
|
- !ruby/object:Gem::Version
|
40
110
|
version: '10.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '10.0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '10.0'
|
41
125
|
- !ruby/object:Gem::Dependency
|
42
126
|
name: minitest
|
43
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +136,20 @@ dependencies:
|
|
52
136
|
- - "~>"
|
53
137
|
- !ruby/object:Gem::Version
|
54
138
|
version: '5.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: minitest
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '5.0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '5.0'
|
55
153
|
- !ruby/object:Gem::Dependency
|
56
154
|
name: sinatra
|
57
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,6 +262,34 @@ dependencies:
|
|
164
262
|
- - ">="
|
165
263
|
- !ruby/object:Gem::Version
|
166
264
|
version: '0'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: rack-test
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - ">="
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '0'
|
272
|
+
type: :development
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ">="
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
279
|
+
- !ruby/object:Gem::Dependency
|
280
|
+
name: rack-test
|
281
|
+
requirement: !ruby/object:Gem::Requirement
|
282
|
+
requirements:
|
283
|
+
- - ">="
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '0'
|
286
|
+
type: :runtime
|
287
|
+
prerelease: false
|
288
|
+
version_requirements: !ruby/object:Gem::Requirement
|
289
|
+
requirements:
|
290
|
+
- - ">="
|
291
|
+
- !ruby/object:Gem::Version
|
292
|
+
version: '0'
|
167
293
|
- !ruby/object:Gem::Dependency
|
168
294
|
name: puma
|
169
295
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,7 +318,37 @@ dependencies:
|
|
192
318
|
- - ">="
|
193
319
|
- !ruby/object:Gem::Version
|
194
320
|
version: '0'
|
195
|
-
|
321
|
+
- !ruby/object:Gem::Dependency
|
322
|
+
name: mushin
|
323
|
+
requirement: !ruby/object:Gem::Requirement
|
324
|
+
requirements:
|
325
|
+
- - ">="
|
326
|
+
- !ruby/object:Gem::Version
|
327
|
+
version: '0'
|
328
|
+
type: :development
|
329
|
+
prerelease: false
|
330
|
+
version_requirements: !ruby/object:Gem::Requirement
|
331
|
+
requirements:
|
332
|
+
- - ">="
|
333
|
+
- !ruby/object:Gem::Version
|
334
|
+
version: '0'
|
335
|
+
- !ruby/object:Gem::Dependency
|
336
|
+
name: mushin
|
337
|
+
requirement: !ruby/object:Gem::Requirement
|
338
|
+
requirements:
|
339
|
+
- - ">="
|
340
|
+
- !ruby/object:Gem::Version
|
341
|
+
version: '0'
|
342
|
+
type: :runtime
|
343
|
+
prerelease: false
|
344
|
+
version_requirements: !ruby/object:Gem::Requirement
|
345
|
+
requirements:
|
346
|
+
- - ">="
|
347
|
+
- !ruby/object:Gem::Version
|
348
|
+
version: '0'
|
349
|
+
description: " Utter is a Domain-specific Microservices Framework written in Ruby.
|
350
|
+
Utter helps you divide up your software project into fun-sized independently deployable
|
351
|
+
API endpoints."
|
196
352
|
email:
|
197
353
|
- zotherstupidguy@gmail.com
|
198
354
|
executables: []
|
@@ -207,17 +363,27 @@ files:
|
|
207
363
|
- README.md
|
208
364
|
- Rakefile
|
209
365
|
- bin/console
|
366
|
+
- bin/scaffold.rb
|
210
367
|
- bin/setup
|
211
|
-
-
|
212
|
-
-
|
213
|
-
-
|
214
|
-
-
|
368
|
+
- bin/templates/README.md
|
369
|
+
- lib/internals/core/auth.rb
|
370
|
+
- lib/internals/core/microservice.rb
|
371
|
+
- lib/internals/core/service_discovery.rb
|
372
|
+
- lib/internals/core/service_registration.rb
|
373
|
+
- lib/internals/core/store.rb
|
374
|
+
- lib/internals/testing/model_delete.rb
|
375
|
+
- lib/internals/testing/spec.rb
|
215
376
|
- lib/utter.rb
|
216
|
-
-
|
217
|
-
-
|
218
|
-
-
|
219
|
-
-
|
220
|
-
- lib/
|
377
|
+
- samples/README.md
|
378
|
+
- samples/upjoystream::v1::auth/Gemfile
|
379
|
+
- samples/upjoystream::v1::auth/Gemfile.lock
|
380
|
+
- samples/upjoystream::v1::auth/config.ru
|
381
|
+
- samples/upjoystream::v1::auth/microservice/lib/app.rb
|
382
|
+
- samples/upjoystream::v1::torrents/Gemfile
|
383
|
+
- samples/upjoystream::v1::torrents/Gemfile.lock
|
384
|
+
- samples/upjoystream::v1::torrents/config.ru
|
385
|
+
- samples/upjoystream::v1::torrents/domain/lib/echo_ext.rb
|
386
|
+
- samples/upjoystream::v1::torrents/microservice/lib/app.rb
|
221
387
|
- utter.gemspec
|
222
388
|
homepage: https://github.com/utter-rb
|
223
389
|
licenses:
|
@@ -239,8 +405,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
239
405
|
version: '0'
|
240
406
|
requirements: []
|
241
407
|
rubyforge_project:
|
242
|
-
rubygems_version: 2.
|
408
|
+
rubygems_version: 2.6.7
|
243
409
|
signing_key:
|
244
410
|
specification_version: 4
|
245
|
-
summary: Utter is
|
411
|
+
summary: Utter is a Domain-specific Microservices Framework written in Ruby.
|
246
412
|
test_files: []
|
data/lib/utter/auth.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
#TODO write RDoc
|
2
|
-
module Utter
|
3
|
-
|
4
|
-
class Auth < Rack::Auth::Basic
|
5
|
-
def call(env)
|
6
|
-
request = Rack::Request.new(env)
|
7
|
-
|
8
|
-
case request.path when '/docs'
|
9
|
-
@app.call(env) # skip auth to access documentation
|
10
|
-
else
|
11
|
-
super # perform auth
|
12
|
-
#TODO use json "sinatra/json" here to ensure all outcoming response are in json
|
13
|
-
|
14
|
-
#res = Rack::Response.new
|
15
|
-
|
16
|
-
# This will automatically set the Content-Length header for you
|
17
|
-
##res.write "Hello from Rack!"
|
18
|
-
|
19
|
-
# You can get/set headers with square bracket syntax:
|
20
|
-
##res["Content-Type"] = "Content-type: application/json; charset=utf-8"
|
21
|
-
|
22
|
-
# returns the standard [status, headers, body] array
|
23
|
-
##res.finish
|
24
|
-
|
25
|
-
# You can set and delete cookies
|
26
|
-
# res.set_cookie("user_id", 1)
|
27
|
-
# res.delete_cookie("user_id"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
# Any class that inherits from Endpoint, may include Utter::Token to add security
|
34
|
-
# token, a token can be used for authenticating a signed-in user or as an API for your system.
|
35
|
-
#
|
36
|
-
# Usage
|
37
|
-
#
|
38
|
-
# via curl https://api.example.com/v1/endpoint_name -u token_value:
|
39
|
-
# via Browser http://token_value@localhost:4567/
|
40
|
-
# If you need to authenticate via bearer auth (e.g., for a cross-origin request), use -H "Authorization: Bearer #{token_value}" instead of -u token_value:
|
41
|
-
#
|
42
|
-
# More Info
|
43
|
-
# - https://en.wikipedia.org/wiki/Digest_access_authentication
|
44
|
-
# - https://github.com/rack/rack/blob/master/lib/rack/auth/basic.rb
|
45
|
-
module Secured
|
46
|
-
def self.included(base)
|
47
|
-
base.class_eval do
|
48
|
-
|
49
|
-
use Auth, "#{self}" do |username, password|
|
50
|
-
|
51
|
-
$log.info "username #{username}, password #{username}"
|
52
|
-
|
53
|
-
if !username.nil? && !password.nil? then
|
54
|
-
if !User.ssd(username).nil? then
|
55
|
-
if password == User.ssd(username).password then
|
56
|
-
true # Access Granted
|
57
|
-
else
|
58
|
-
false # Access Denied
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# 404 Error!
|
65
|
-
not_found do
|
66
|
-
status 404
|
67
|
-
"404 - Check #{self} API documentation"
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
data/lib/utter/endpoint.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#TODO write RDoc
|
2
|
-
require 'fileutils'
|
3
|
-
require 'sinatra'
|
4
|
-
require "sinatra/json"
|
5
|
-
require 'securerandom'
|
6
|
-
require 'sinatra/cross_origin'
|
7
|
-
require 'net/http' # Net::HTTP.get('example.com', '/index.html') # => String
|
8
|
-
|
9
|
-
module Utter
|
10
|
-
class Endpoint < Sinatra::Base
|
11
|
-
# if cross_origin is required\loaded then make register Sinatra::CrossOrigin
|
12
|
-
# And
|
13
|
-
#register Sinatra::CrossOrigin
|
14
|
-
|
15
|
-
#TODO set a flag to disable this in production for security
|
16
|
-
# this helps testing APIs on localmachines as CORS fucks developers time.
|
17
|
-
# But not recommended to be set while in production enviroments
|
18
|
-
before do
|
19
|
-
response.headers["Access-Control-Allow-Origin"] = "*"
|
20
|
-
response.headers["Access-Control-Allow-Methods"] = "POST"
|
21
|
-
p response.headers.inspect
|
22
|
-
end
|
23
|
-
|
24
|
-
configure { set :server, :puma }
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
data/lib/utter/version.rb
DELETED
File without changes
|
File without changes
|
File without changes
|