Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(console): fix bug & add pytest for project api #970

Merged
merged 4 commits into from
Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 80 additions & 23 deletions scripts/apitest/pytest/test_project.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import requests
import pytest
import time
import os
from common import httputil as hu


class TestProject:
def get_project(host, port, name):
url = '{api}/project/{project}'
res = requests.get(url=url.format(api=hu.url(host, port), project=name),
headers=hu.header())
return res


class TestProject:
def test_login(self, host, port):
hu.login(host, port)

def test_list(self, host, port):
res = requests.get(url=hu.url(host, port) + '/project',
url = '{api}/project'
res = requests.get(url=url.format(api=hu.url(host, port)),
headers=hu.header())
response = res.json()

Expand All @@ -20,8 +29,15 @@ def test_list(self, host, port):
print('Test project list ok.')

def test_create(self, host, port):
res = requests.post(url=hu.url(host, port) + '/project',
json={'projectName': 'project_for_test'},
url = '{api}/project'
sec = str(int(time.time()))
project_name = 'pytest' + sec
os.environ['project_name'] = project_name
res = requests.post(url=url.format(api=hu.url(host, port)),
json={'projectName': project_name,
'privacy': 'public',
'ownerId': 1,
'description': 'project for pytest'},
headers=hu.header())
response = res.json()

Expand All @@ -31,61 +47,102 @@ def test_create(self, host, port):
print('Test Project Create ok.')

def test_info(self, host, port):
res = requests.get(url=hu.url(host, port) + '/project/project_for_test',
headers=hu.header())
project_name = os.getenv('project_name')
res = get_project(host, port, project_name)
response = res.json()

assert res.status_code == 200
assert response['code'] == 'success'
assert response['data']['name'] == 'project_for_test'
assert response['data']['name'] == project_name
assert response['data']['privacy'] == 'PUBLIC'
assert response['data']['description'] == 'project for pytest'

print('Test Project get information ok.')

def test_project_role(self, host, port):
url = '{api}/project/{project}/role'
project_name = os.getenv('project_name')
res = requests.get(url=url.format(api=hu.url(host, port),
project=project_name),
headers=hu.header())
response = res.json()
assert res.status_code == 200
assert len(response['data']) > 0

def test_modify(self, host, port):
res = requests.put(url=hu.url(host, port) + '/project'
'/project_for_test',
json={'projectName': 'project_test_modify'},
url = '{api}/project/{project}'
project_name = os.getenv('project_name')
project_name_modified = project_name + "_modified"
res = requests.put(url=url.format(api=hu.url(host, port),
project=project_name),
json={'projectName': project_name_modified,
'privacy': 'private',
'description': 'modified description'},
headers=hu.header())
response = res.json()

assert res.status_code == 200
assert response['code'] == 'success'

res = get_project(host, port, project_name_modified)
response = res.json()

assert res.status_code == 200
assert response['code'] == 'success'
assert response['data']['name'] == project_name_modified
assert response['data']['privacy'] == 'PRIVATE'
assert response['data']['description'] == 'modified description'

print('Test Project Modify ok.')

def test_remove(self, host, port):
res = requests.delete(url=hu.url(host, port) + '/project'
'/project_test_modify',
url = '{api}/project/{project}'
project_name_modified = os.getenv('project_name') + "_modified"
res = requests.delete(url=url.format(api=hu.url(host, port),
project=project_name_modified),
headers=hu.header())
response = res.json()

assert res.status_code == 200
assert response['code'] == 'success'

res = get_project(host, port, project_name_modified)
assert res.status_code == 404 or res.status_code == 400

print('Test Project Remove ok.')

def test_recover(self, host, port):
res = requests.post(url=hu.url(host, port) + '/project',
json={'projectName': 'project_for_recover'},
url = '{api}/project'
project_name_recover = os.getenv('project_name') + "_recover"
res = requests.post(url=url.format(api=hu.url(host, port)),
json={'projectName': project_name_recover,
'privacy': 'private',
'ownerId': 1,
'description': ''},
headers=hu.header())
response = res.json()
data = response['data']
pid = response['data']

requests.delete(url=hu.url(host, port) + '/project'
'/' + data,
url = '{api}/project/{project}'
requests.delete(url=url.format(api=hu.url(host, port),
project=pid),
headers=hu.header())

res = requests.post(url=hu.url(host, port) + '/project',
json={'projectId': data,
'recover': 'true'},
headers=hu.header())
url = '{api}/project/{project}/recover'
res = requests.put(url=url.format(api=hu.url(host, port),
project=pid),
headers=hu.header())
response = res.json()

assert res.status_code == 200
assert response['code'] == 'success'

requests.delete(url=hu.url(host, port) + '/project'
'/' + data,
res = get_project(host, port, pid)
assert res.status_code == 200

url = '{api}/project/{project}'
requests.delete(url=url.format(api=hu.url(host, port),
project=pid),
headers=hu.header())

print('Test Project Recover ok.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@
package ai.starwhale.mlops.api;

import ai.starwhale.mlops.api.protocol.ResponseMessage;
import ai.starwhale.mlops.api.protocol.project.ProjectRequest;
import ai.starwhale.mlops.api.protocol.project.CreateProjectRequest;
import ai.starwhale.mlops.api.protocol.project.UpdateProjectRequest;
import ai.starwhale.mlops.api.protocol.project.ProjectVO;
import ai.starwhale.mlops.api.protocol.user.ProjectRoleVO;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand Down Expand Up @@ -67,7 +66,7 @@ ResponseEntity<ResponseMessage<PageInfo<ProjectVO>>> listProject(
@PostMapping(value = "/project")
@PreAuthorize("hasAnyRole('OWNER', 'MAINTAINER')")
ResponseEntity<ResponseMessage<String>> createProject(
@Valid @RequestBody ProjectRequest projectRequest);
@Valid @RequestBody CreateProjectRequest createProjectRequest);


@Operation(summary = "Delete a project by Url")
Expand All @@ -81,10 +80,10 @@ ResponseEntity<ResponseMessage<String>> deleteProjectByUrl(
@Operation(summary = "Recover a project")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "ok")})
@PutMapping(value = "/project/{projectUrl}/recover")
@PutMapping(value = "/project/{projectId}/recover")
@PreAuthorize("hasAnyRole('OWNER')")
ResponseEntity<ResponseMessage<String>> recoverProject(
@Valid @PathVariable("projectUrl") String projectUrl);
@Valid @PathVariable("projectId") String projectId);


@Operation(summary = "Get a project by Url", description = "Returns a single project object.")
Expand All @@ -105,7 +104,7 @@ ResponseEntity<ResponseMessage<ProjectVO>> getProjectByUrl(
@PreAuthorize("hasAnyRole('OWNER', 'MAINTAINER')")
ResponseEntity<ResponseMessage<String>> updateProject(
@PathVariable("projectUrl") String projectId,
@Valid @RequestBody ProjectRequest projectRequest);
@Valid @RequestBody UpdateProjectRequest updateProjectRequest);


@Operation(summary = "List project roles")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@

import ai.starwhale.mlops.api.protocol.Code;
import ai.starwhale.mlops.api.protocol.ResponseMessage;
import ai.starwhale.mlops.api.protocol.project.ProjectRequest;
import ai.starwhale.mlops.api.protocol.project.CreateProjectRequest;
import ai.starwhale.mlops.api.protocol.project.ProjectVO;
import ai.starwhale.mlops.api.protocol.project.UpdateProjectRequest;
import ai.starwhale.mlops.api.protocol.user.ProjectRoleVO;
import ai.starwhale.mlops.common.IDConvertor;
import ai.starwhale.mlops.common.OrderParams;
Expand Down Expand Up @@ -75,26 +76,18 @@ public ResponseEntity<ResponseMessage<PageInfo<ProjectVO>>> listProject(String p
}

@Override
public ResponseEntity<ResponseMessage<String>> createProject(ProjectRequest projectRequest) {
Long projectId;
if(Boolean.TRUE.equals(projectRequest.getRecover())) {
String projectUrl = projectRequest.getProjectId();
if(projectUrl == null) {
projectUrl = projectRequest.getProjectName();
}
projectId = projectService.recoverProject(projectUrl);
} else {
projectId = projectService
public ResponseEntity<ResponseMessage<String>> createProject(
CreateProjectRequest createProjectRequest) {
Long projectId = projectService
.createProject(Project.builder()
.name(projectRequest.getProjectName())
.name(createProjectRequest.getProjectName())
.owner(User.builder()
.id(idConvertor.revert(projectRequest.getOwnerId()))
.id(idConvertor.revert(createProjectRequest.getOwnerId()))
.build())
.isDefault(false)
.privacy(Privacy.fromName(projectRequest.getPrivacy()))
.description(projectRequest.getDescription())
.privacy(Privacy.fromName(createProjectRequest.getPrivacy()))
.description(createProjectRequest.getDescription())
.build());
}

return ResponseEntity.ok(Code.success.asResponse(idConvertor.convert(projectId)));

Expand All @@ -111,8 +104,8 @@ public ResponseEntity<ResponseMessage<String>> deleteProjectByUrl(String project
}

@Override
public ResponseEntity<ResponseMessage<String>> recoverProject(String projectUrl) {
projectService.recoverProject(projectUrl);
public ResponseEntity<ResponseMessage<String>> recoverProject(String projectId) {
projectService.recoverProject(projectId);
return ResponseEntity.ok(Code.success.asResponse("success"));
}

Expand All @@ -124,12 +117,12 @@ public ResponseEntity<ResponseMessage<ProjectVO>> getProjectByUrl(String project

@Override
public ResponseEntity<ResponseMessage<String>> updateProject(String projectUrl,
ProjectRequest projectRequest) {
UpdateProjectRequest updateProjectRequest) {
Boolean res = projectService.modifyProject(projectUrl,
projectRequest.getProjectName(),
projectRequest.getDescription(),
idConvertor.revert(projectRequest.getOwnerId()),
projectRequest.getPrivacy()
updateProjectRequest.getProjectName(),
updateProjectRequest.getDescription(),
idConvertor.revert(updateProjectRequest.getOwnerId()),
updateProjectRequest.getPrivacy()
);
if(!res) {
throw new StarWhaleApiException(new SWProcessException(ErrorType.DB).tip("Update project failed."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,24 @@

@Data
@Validated
public class ProjectRequest implements Serializable {
public class CreateProjectRequest implements Serializable {


@JsonProperty("projectName")
@NotNull
@Pattern(regexp = RegExps.PROJECT_NAME_REGEX, message = "Project name is invalid.")
private String projectName;

@JsonProperty("projectId")
private String projectId;

@NotNull
@JsonProperty("ownerId")
private String ownerId;

@NotNull
@JsonProperty("privacy")
private String privacy;

@NotNull
@JsonProperty("description")
private String description;

@JsonProperty(value = "recover", defaultValue = "false", required = true)
private Boolean recover;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ai.starwhale.mlops.api.protocol.project;

import ai.starwhale.mlops.common.RegExps;
import com.fasterxml.jackson.annotation.JsonProperty;
import javax.validation.constraints.Pattern;
import lombok.Data;
import org.springframework.validation.annotation.Validated;

@Data
@Validated
public class UpdateProjectRequest {

@JsonProperty("projectName")
@Pattern(regexp = RegExps.PROJECT_NAME_REGEX, message = "Project name is invalid.")
private String projectName;

@JsonProperty("ownerId")
private String ownerId;

@JsonProperty("privacy")
private String privacy;

@JsonProperty("description")
private String description;
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,4 @@ public static String getResourceUrlFromPath(String path, String resourceName) {
return null;
}
}

public static void main(String[] args) {
System.out.println(getResourceUrlFromPath("/api/v1/project/project_test_1", Resources.PROJECT));
System.out.println(getResourceUrlFromPath("/api/v1/project/project_test_1/model/1", Resources.PROJECT));
System.out.println(getResourceUrlFromPath("/project/project_test_1?pageSize=1", Resources.PROJECT));
System.out.println(getResourceUrlFromPath("/project/project_test_1?pageSize=1", Resources.RUNTIME));
System.out.println(getResourceUrlFromPath("/api/v1/project/project_test_1/model/1", Resources.MODEL));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public Boolean modifyProject(String projectUrl, String projectName, String descr
.projectName(projectName)
.description(description)
.ownerId(userId)
.privacy(Privacy.fromName(privacy).getValue())
.privacy(privacy == null ? null : Privacy.fromName(privacy).getValue())
.build();
int res = projectMapper.modifyProject(entity);
log.info("Project has been modified ID={}", entity.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
rel.modified_time as project_role_modified_time,
r.role_code,
r.role_name,
r.role_description ,
r.role_description,
u.user_name,
u.user_enabled,
u.created_time as user_created_time,
Expand All @@ -33,6 +33,7 @@
view.*,
p.project_name,
p.is_deleted,
p.privacy as project_privacy,
p.created_time as project_created_time,
p.modified_time as project_modified_time
from (select rel.id as project_role_id,
Expand Down Expand Up @@ -62,6 +63,7 @@
view.*,
p.project_name,
p.is_deleted,
p.privacy as project_privacy,
p.created_time as project_created_time,
p.modified_time as project_modified_time
from (select rel.id as project_role_id,
Expand Down Expand Up @@ -113,6 +115,7 @@
<resultMap id="projectResultMap" type="ai.starwhale.mlops.domain.project.po.ProjectEntity">
<id property="id" column="project_id" />
<result property="projectName" column="project_name"/>
<result property="privacy" column="project_privacy"/>
<result property="createdTime" column="project_created_time"/>
<result property="modifiedTime" column="project_modified_time"/>
</resultMap>
Expand Down
Loading