Skip to content

Commit d3218cd

Browse files
author
yang.guo
authored
Merge pull request #138 from FlowCI/develop
Develop
2 parents 7b4a95f + d7d785f commit d3218cd

File tree

174 files changed

+5981
-1684
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+5981
-1684
lines changed

config/app-api.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ domain.api = http://localhost:8080
2525
domain.web = http://localhost:3000
2626
domain.cc = http://localhost:8080
2727

28+
system.email = [email protected]
29+
system.username = admin
30+
system.password = 123456
31+
2832
task.job.toggle.execution_timeout = false
2933
## 6s expire job
3034
task.job.toggle.execution_create_session_duration = 600

platform-api/README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414

1515
**FLOW_YML_ERROR_MSG**: error message if FLOW_YML_STATUS = ERROR
1616

17-
**FLOW_DEPLOY_KEY_NAME**: the credential name for RSA deploy key pair
17+
**FLOW_ENV_OUTPUT_PREFIX**: env output prefix used for pass env variable which start with this prefix to next step
18+
19+
**FLOW_TASK_CRONTAB_CONTENT**: flow crontab content, the format like * * * * * ?,
20+
and FLOW_TASK_CRONTAB_BRANCH are required
21+
22+
**FLOW_TASK_CRONTAB_BRANCH**: flow crontab branch
23+
1824

1925
### Job
2026

@@ -24,6 +30,8 @@
2430

2531
**FLOW_JOB_AGENT_INFO**: readonly, the agent path which job running on as 'zone#name' format
2632

33+
**FLOW_JOB_LOG_PATH**: readonly: the download path for job log
34+
2735
### Git
2836
2937
**FLOW_GIT_SOURCE**: {UNDEFINED_SSH | UNDEFINED_HTTP | GITLAB | GITHUB| CODING| OSCHINA | BITBUCKET}

platform-api/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,16 @@
149149
<artifactId>velocity</artifactId>
150150
</dependency>
151151

152+
<dependency>
153+
<groupId>org.quartz-scheduler</groupId>
154+
<artifactId>quartz</artifactId>
155+
</dependency>
156+
157+
<dependency>
158+
<groupId>org.quartz-scheduler</groupId>
159+
<artifactId>quartz-jobs</artifactId>
160+
</dependency>
161+
152162
<dependency>
153163
<groupId>junit</groupId>
154164
<artifactId>junit</artifactId>

platform-api/src/main/java/com/flow/platform/api/config/AppConfig.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,27 @@
3434
import org.apache.velocity.app.VelocityEngine;
3535
import org.apache.velocity.runtime.RuntimeConstants;
3636
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
37+
import org.springframework.beans.factory.annotation.Autowired;
3738
import org.springframework.beans.factory.annotation.Value;
3839
import org.springframework.context.annotation.Bean;
3940
import org.springframework.context.annotation.Configuration;
4041
import org.springframework.context.annotation.Import;
4142
import org.springframework.context.event.ApplicationEventMulticaster;
4243
import org.springframework.context.event.SimpleApplicationEventMulticaster;
44+
import org.springframework.scheduling.TaskScheduler;
45+
import org.springframework.scheduling.annotation.EnableScheduling;
4346
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
4447

4548
/**
4649
* @author yang
4750
*/
4851
@Configuration
49-
@Import({CachingConfig.class, DatabaseConfig.class})
52+
@Import({SchedulerConfig.class, CachingConfig.class, DatabaseConfig.class})
5053
public class AppConfig extends AppConfigBase {
5154

5255
public final static String NAME = "API";
5356

54-
public final static String VERSION = "0.1.0";
57+
public final static String VERSION = "v0.1-alpha";
5558

5659
public final static String DEFAULT_YML_FILE = ".flow.yml";
5760

@@ -67,11 +70,6 @@ public class AppConfig extends AppConfigBase {
6770

6871
private final static int MULTICASTER_ASYNC_POOL_SIZE = 1;
6972

70-
public final static String DEFAULT_USER_EMAIL = "[email protected]";
71-
public final static String DEFAULT_USER_NAME = "admin";
72-
73-
public final static String DEFAULT_USER_PASSWORD = "123456";
74-
7573
private final static ThreadPoolTaskExecutor executor =
7674
ThreadUtil.createTaskExecutor(ASYNC_POOL_SIZE, ASYNC_POOL_SIZE / 10, 100, THREAD_NAME_PREFIX);
7775

@@ -85,6 +83,20 @@ public class AppConfig extends AppConfigBase {
8583
@Value("${domain.cc}")
8684
private String ccDomain;
8785

86+
@Value(value = "${system.email}")
87+
private String email;
88+
89+
@Value(value = "${system.username}")
90+
private String username;
91+
92+
@Value(value = "${system.password}")
93+
private String password;
94+
95+
@Bean
96+
public User superUser() {
97+
return new User(email, username, password);
98+
}
99+
88100
@Bean
89101
public Path workspace() {
90102
try {
@@ -125,7 +137,7 @@ public ThreadPoolTaskExecutor taskExecutor() {
125137
*/
126138
@Bean
127139
public PlatformQueue<CmdCallbackQueueItem> cmdCallbackQueue() {
128-
return new InMemoryQueue<>(executor, 50);
140+
return new InMemoryQueue<>(executor, 50, "CmdCallbackQueue");
129141
}
130142

131143
@Override
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2017 flow.ci
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.flow.platform.api.config;
18+
19+
import com.flow.platform.api.task.NodeCrontabTask;
20+
import com.flow.platform.core.exception.IllegalStatusException;
21+
import java.io.IOException;
22+
import org.quartz.JobBuilder;
23+
import org.quartz.JobDetail;
24+
import org.quartz.Scheduler;
25+
import org.quartz.SchedulerException;
26+
import org.quartz.impl.StdSchedulerFactory;
27+
import org.springframework.beans.factory.annotation.Configurable;
28+
import org.springframework.context.annotation.Bean;
29+
import org.springframework.core.io.ClassPathResource;
30+
import org.springframework.scheduling.annotation.EnableScheduling;
31+
import org.springframework.scheduling.annotation.SchedulingConfigurer;
32+
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
33+
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
34+
35+
/**
36+
* @author yang
37+
*/
38+
@Configurable
39+
@EnableScheduling
40+
public class SchedulerConfig implements SchedulingConfigurer {
41+
42+
private final static int DEFAULT_SCHEDULER_POOL_SIZE = 10;
43+
44+
/**
45+
* Thread pool for spring scheduling
46+
*/
47+
@Bean(destroyMethod = "shutdown")
48+
public ThreadPoolTaskScheduler schedulerTaskExecutor() {
49+
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
50+
scheduler.setPoolSize(DEFAULT_SCHEDULER_POOL_SIZE);
51+
scheduler.setDaemon(true);
52+
scheduler.setThreadNamePrefix("api-task-");
53+
scheduler.initialize();
54+
return scheduler;
55+
}
56+
57+
/**
58+
* Setup quartz scheduler
59+
*/
60+
@Bean
61+
public Scheduler quartzScheduler() {
62+
try {
63+
StdSchedulerFactory factory = new StdSchedulerFactory();
64+
factory.initialize(new ClassPathResource("quartz.properties").getInputStream());
65+
return factory.getScheduler();
66+
} catch (SchedulerException | IOException e) {
67+
throw new IllegalStatusException("Unable to init quartz: " + e.getMessage());
68+
}
69+
}
70+
71+
/**
72+
* Setup flow crontab job detail
73+
*/
74+
@Bean
75+
public JobDetail nodeCrontabDetail() {
76+
return JobBuilder.newJob(NodeCrontabTask.class).storeDurably(true).build();
77+
}
78+
79+
@Override
80+
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
81+
taskRegistrar.setTaskScheduler(schedulerTaskExecutor());
82+
}
83+
}

platform-api/src/main/java/com/flow/platform/api/config/WebConfig.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.flow.platform.api.resource.PropertyResourceLoader;
2020
import com.flow.platform.api.security.AuthenticationInterceptor;
21+
import com.flow.platform.api.security.OptionsInterceptor;
2122
import com.flow.platform.api.security.token.JwtTokenGenerator;
2223
import com.flow.platform.api.security.token.TokenGenerator;
2324
import com.flow.platform.core.http.converter.RawGsonMessageConverter;
@@ -44,6 +45,7 @@
4445
import org.springframework.scheduling.annotation.EnableScheduling;
4546
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
4647
import org.springframework.security.web.util.matcher.RequestMatcher;
48+
import org.springframework.web.context.request.WebRequestInterceptor;
4749
import org.springframework.web.multipart.MultipartResolver;
4850
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
4951
import org.springframework.web.servlet.config.annotation.CorsRegistry;
@@ -53,11 +55,11 @@
5355

5456
@Configuration
5557
@EnableWebMvc
56-
@EnableScheduling
5758
@ComponentScan({
5859
"com.flow.platform.core.controller",
5960
"com.flow.platform.api.controller",
6061
"com.flow.platform.api.service",
62+
"com.flow.platform.api.envs.handler",
6163
"com.flow.platform.api.security",
6264
"com.flow.platform.api.dao",
6365
"com.flow.platform.api.context",
@@ -113,21 +115,30 @@ public AuthenticationInterceptor authInterceptor() {
113115
List<RequestMatcher> matchers = Lists.newArrayList(
114116
new AntPathRequestMatcher("/flows/**"),
115117
new AntPathRequestMatcher("/user/register"),
118+
new AntPathRequestMatcher("/user/delete"),
119+
new AntPathRequestMatcher("/user"),
120+
new AntPathRequestMatcher("/user/role/update"),
116121
new AntPathRequestMatcher("/jobs/**"),
117122
new AntPathRequestMatcher("/credentials/**"),
118123
new AntPathRequestMatcher("/actions/**"),
119-
new AntPathRequestMatcher("/message/**")
124+
new AntPathRequestMatcher("/message/**"),
125+
new AntPathRequestMatcher("/agents/create"),
126+
new AntPathRequestMatcher("/agents"),
127+
new AntPathRequestMatcher("/roles/**"),
128+
new AntPathRequestMatcher("/thread/config")
120129
);
121130
return new AuthenticationInterceptor(matchers);
122131
}
123132

133+
124134
@Bean
125135
public RawGsonMessageConverter jsonConverter() {
126136
return this.jsonConverter;
127137
}
128138

129139
@Override
130140
public void addInterceptors(InterceptorRegistry registry) {
141+
registry.addInterceptor(new OptionsInterceptor());
131142
registry.addInterceptor(authInterceptor());
132143
}
133144

platform-api/src/main/java/com/flow/platform/api/consumer/CmdCallbackQueueConsumer.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.flow.platform.api.domain.CmdCallbackQueueItem;
2020
import com.flow.platform.api.service.job.JobService;
21+
import com.flow.platform.core.exception.NotFoundException;
2122
import com.flow.platform.core.queue.PlatformQueue;
2223
import com.flow.platform.core.queue.QueueListener;
2324
import com.flow.platform.util.Logger;
@@ -51,8 +52,22 @@ public void onQueueItem(CmdCallbackQueueItem item) {
5152
}
5253
try {
5354
jobService.callback(item);
54-
}catch (Throwable throwable){
55+
} catch (NotFoundException notFoundException) {
56+
57+
// re-enqueue cmd callback if job not found since transaction problem
58+
reEnqueueJobCallback(item, 1000);
59+
60+
} catch (Throwable throwable) {
5561
LOGGER.traceMarker("onQueueItem", String.format("exception - %s", throwable));
5662
}
5763
}
64+
65+
private void reEnqueueJobCallback(CmdCallbackQueueItem item, long wait) {
66+
try {
67+
Thread.sleep(wait);
68+
} catch (Throwable ignore) {
69+
}
70+
71+
jobService.enterQueue(item);
72+
}
5873
}

platform-api/src/main/java/com/flow/platform/api/consumer/JobEventPushHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ protected void push(Job job) {
4646
} catch (NotFoundException e) {
4747
jobConsist = job;
4848
}
49+
jobConsist.setStatus(job.getStatus());
4950
String jobTopic = String.format("%s/%s", WebSocketConfig.TOPIC_FOR_JOB, jobConsist.getNodePath());
5051
super.push(jobTopic, jobConsist);
5152
}

platform-api/src/main/java/com/flow/platform/api/controller/ActionController.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
*/
1616
package com.flow.platform.api.controller;
1717

18+
import com.flow.platform.api.domain.permission.Actions;
1819
import com.flow.platform.api.domain.request.ActionParam;
1920
import com.flow.platform.api.domain.user.Action;
21+
import com.flow.platform.api.security.WebSecurity;
2022
import com.flow.platform.api.service.user.ActionService;
2123
import java.util.List;
2224
import org.springframework.beans.factory.annotation.Autowired;
2325
import org.springframework.web.bind.annotation.GetMapping;
2426
import org.springframework.web.bind.annotation.PatchMapping;
2527
import org.springframework.web.bind.annotation.PathVariable;
28+
import org.springframework.web.bind.annotation.PostMapping;
2629
import org.springframework.web.bind.annotation.RequestBody;
2730
import org.springframework.web.bind.annotation.RequestMapping;
2831
import org.springframework.web.bind.annotation.RestController;
@@ -55,6 +58,7 @@ public class ActionController {
5558
* ]
5659
*/
5760
@GetMapping
61+
@WebSecurity(action = Actions.ADMIN_SHOW)
5862
public List<Action> index() {
5963
return actionService.list();
6064
}
@@ -81,7 +85,36 @@ public List<Action> index() {
8185
* }
8286
*/
8387
@PatchMapping(path = "/{name}")
88+
@WebSecurity(action = Actions.ADMIN_UPDATE)
8489
public Action update(@PathVariable String name, @RequestBody ActionParam body) {
8590
return actionService.update(name, body);
8691
}
92+
93+
/**
94+
* @api {post} /actions
95+
* @apiParam {String} create action
96+
* @apiParamExample {json} Request-Body
97+
* {
98+
* name: FLOW_CREATE,
99+
* description: xxx,
100+
* tag: USER
101+
* }
102+
* @apiGroup Action
103+
*
104+
* @apiSuccessExample {json} Success-Response
105+
* {
106+
* name: FLOW_CREATE,
107+
* alias: create flow,
108+
* description: xxxx,
109+
* tag: DEFAULT,
110+
* createdAt: xxx,
111+
* updatedAt: xxx
112+
* }
113+
*/
114+
115+
@PostMapping
116+
@WebSecurity(action = Actions.ADMIN_CREATE)
117+
public Action create(@RequestBody Action action) {
118+
return actionService.create(action);
119+
}
87120
}

0 commit comments

Comments
 (0)