Skip to content

Commit b047822

Browse files
refactors and add tests
1 parent b630cf3 commit b047822

9 files changed

Lines changed: 271 additions & 10 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,9 @@ public class ApiConstants {
13281328
public static final String OBJECT_STORAGE_LIMIT = "objectstoragelimit";
13291329
public static final String OBJECT_STORAGE_TOTAL = "objectstoragetotal";
13301330

1331+
// NIMBLE related
1332+
public static final String IAC_RESOURCE_TYPE_CONTENT = "iacresourcetypecontent";
1333+
13311334
public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +
13321335
"a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " +
13331336
"numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " +

plugins/iac/nimble/src/main/java/org/apache/cloudstack/api/response/IacResourceTypeResponse.java

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,48 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.response;
1818

19-
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
19+
import com.cloud.serializer.Param;
20+
import com.google.gson.annotations.SerializedName;
21+
import org.apache.cloudstack.api.ApiConstants;
22+
import org.apache.cloudstack.api.BaseResponse;
2023
import org.apache.cloudstack.api.EntityReference;
24+
import org.apache.cloudstack.persistence.iactemplatesprofile.IacResourceType;
2125

22-
@EntityReference(value = {})
23-
public class IacResourceTypeResponse extends BaseResponseWithAnnotations {
26+
@EntityReference(value = {IacResourceType.class})
27+
public class IacResourceTypeResponse extends BaseResponse {
28+
@SerializedName(ApiConstants.ID)
29+
@Param(description = "The ID of the IaC resource type.")
30+
private String id;
31+
32+
@SerializedName(ApiConstants.NAME)
33+
@Param(description = "The name of the IaC resource type.")
34+
private String name;
35+
36+
@SerializedName(ApiConstants.IAC_RESOURCE_TYPE_CONTENT)
37+
@Param(description = "The content of the IaC resource type.")
38+
private String iacResourceTypeContent;
39+
40+
public String getId() {
41+
return id;
42+
}
43+
44+
public void setId(String id) {
45+
this.id = id;
46+
}
47+
48+
public String getName() {
49+
return name;
50+
}
51+
52+
public void setName(String name) {
53+
this.name = name;
54+
}
55+
56+
public String getIacResourceTypeContent() {
57+
return iacResourceTypeContent;
58+
}
59+
60+
public void setIacResourceTypeContent(String iacResourceTypeContent) {
61+
this.iacResourceTypeContent = iacResourceTypeContent;
62+
}
2463
}

plugins/iac/nimble/src/main/java/org/apache/cloudstack/api/response/NimbleResponseBuilder.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,14 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.response;
1818

19+
import org.apache.cloudstack.persistence.iactemplatesprofile.IacResourceType;
20+
1921
public class NimbleResponseBuilder {
22+
public IacResourceTypeResponse createIacResourceTypeResponse(IacResourceType iacResourceType) {
23+
IacResourceTypeResponse response = new IacResourceTypeResponse();
24+
response.setId(iacResourceType.getUuid());
25+
response.setName(iacResourceType.getName());
26+
response.setIacResourceTypeContent(iacResourceType.getContent());
27+
return response;
28+
}
2029
}

plugins/iac/nimble/src/main/java/org/apache/cloudstack/persistence/iactemplatesprofile/IacResourceType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@
2121

2222
public interface IacResourceType extends Identity, InternalIdentity {
2323
String getName();
24-
String getElementContent();
24+
String getContent();
2525
}

plugins/iac/nimble/src/main/java/org/apache/cloudstack/persistence/iactemplatesprofile/IacResourceTypeDaoImpl.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,41 @@
1616
// under the License.
1717
package org.apache.cloudstack.persistence.iactemplatesprofile;
1818

19+
import com.cloud.utils.Pair;
20+
import com.cloud.utils.db.Filter;
1921
import com.cloud.utils.db.GenericDaoBase;
22+
import com.cloud.utils.db.SearchBuilder;
23+
import com.cloud.utils.db.SearchCriteria;
2024
import org.springframework.stereotype.Component;
2125

26+
import java.util.List;
27+
2228
@Component
2329
public class IacResourceTypeDaoImpl extends GenericDaoBase<IacResourceTypeVO, Long> implements IacResourceTypeDao {
30+
private static final String ID = "id";
31+
private static final String NAME = "name";
32+
private static final String NAME_LIKE_KEYWORD = "nameLikeKeyword";
33+
34+
private final SearchBuilder<IacResourceTypeVO> listIacResourceTypesSearchBuilder;
35+
36+
public IacResourceTypeDaoImpl() {
37+
listIacResourceTypesSearchBuilder = createSearchBuilder();
38+
listIacResourceTypesSearchBuilder.and(ID, listIacResourceTypesSearchBuilder.entity().getId(), SearchCriteria.Op.EQ);
39+
listIacResourceTypesSearchBuilder.and(NAME, listIacResourceTypesSearchBuilder.entity().getName(), SearchCriteria.Op.EQ);
40+
listIacResourceTypesSearchBuilder.and(NAME_LIKE_KEYWORD, listIacResourceTypesSearchBuilder.entity().getName(), SearchCriteria.Op.LIKE);
41+
listIacResourceTypesSearchBuilder.done();
42+
}
43+
44+
@Override
45+
public Pair<List<IacResourceTypeVO>, Integer> listIacResourceTypes(Long id, String name, String keyword, Long pageSizeVal, Long startIndex) {
46+
SearchCriteria<IacResourceTypeVO> searchCriteria = listIacResourceTypesSearchBuilder.create();
47+
searchCriteria.setParametersIfNotNull(ID, id);
48+
searchCriteria.setParametersIfNotNull(NAME, name);
49+
if (keyword != null) {
50+
searchCriteria.setParameters(NAME_LIKE_KEYWORD, "%" + keyword + "%");
51+
}
52+
53+
Filter filter = new Filter(IacResourceTypeVO.class, ID, true, startIndex, pageSizeVal);
54+
return searchAndCount(searchCriteria, filter);
55+
}
2456
}

plugins/iac/nimble/src/main/java/org/apache/cloudstack/persistence/iactemplatesprofile/IacResourceTypeVO.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ public class IacResourceTypeVO implements IacResourceType {
3838
@Column(name = "name", nullable = false, length = 100)
3939
private String name;
4040

41-
@Column(name = "element_content", nullable = false, length = 65535)
42-
private String elementContent;
41+
@Column(name = "content", nullable = false, length = 65535)
42+
private String content;
4343

4444
@Override
4545
public long getId() {
@@ -57,7 +57,7 @@ public String getName() {
5757
}
5858

5959
@Override
60-
public String getElementContent() {
61-
return elementContent;
60+
public String getContent() {
61+
return content;
6262
}
6363
}

plugins/iac/nimble/src/main/java/org/apache/cloudstack/service/NimbleManagerImpl.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ public class NimbleManagerImpl extends ManagerBase implements NimbleService {
5555
public ListResponse<IacResourceTypeResponse> listIacResourceTypes(ListIacResourceTypesCmd cmd) {
5656
Pair<List<IacResourceTypeVO>, Integer> iacResourceTypes = iacResourceTypeDao.listIacResourceTypes(cmd.getId(), cmd.getName(),
5757
cmd.getKeyword(), cmd.getPageSizeVal(), cmd.getStartIndex());
58-
List<IacResourceTypeResponse> iacResourceTypeResponses = iacResourceTypes.first().stream().map(iacResourceType -> new IacResourceTypeResponse()).collect(Collectors.toList());
58+
List<IacResourceTypeResponse> iacResourceTypeResponses = iacResourceTypes.first().stream()
59+
.map(iacResourceType -> responseBuilder.createIacResourceTypeResponse(iacResourceType))
60+
.collect(Collectors.toList());
61+
5962
ListResponse<IacResourceTypeResponse> response = new ListResponse<>();
6063
response.setResponses(iacResourceTypeResponses, iacResourceTypes.second());
6164
return response;
@@ -77,7 +80,7 @@ protected Map<String, ToscaNodeType> loadToscaProfile() {
7780
List<IacResourceTypeVO> profileResourceTypes = iacResourceTypeDao.listAll();
7881

7982
return profileResourceTypes.stream()
80-
.map(resourceType -> toscaParser.parseNodeType(resourceType.getName(), resourceType.getElementContent()))
83+
.map(resourceType -> toscaParser.parseNodeType(resourceType.getName(), resourceType.getContent()))
8184
.collect(Collectors.toMap(ToscaNodeType::getName, nodeType -> nodeType));
8285
}
8386

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.api.response;
18+
19+
import org.apache.cloudstack.persistence.iactemplatesprofile.IacResourceTypeVO;
20+
import org.junit.Assert;
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
import org.mockito.InjectMocks;
24+
import org.mockito.Mock;
25+
import org.mockito.Mockito;
26+
import org.mockito.Spy;
27+
import org.mockito.junit.MockitoJUnitRunner;
28+
29+
@RunWith(MockitoJUnitRunner.class)
30+
public class NimbleResponseBuilderTest {
31+
@Spy
32+
@InjectMocks
33+
private NimbleResponseBuilder nimbleResponseBuilderSpy;
34+
35+
@Mock
36+
private IacResourceTypeVO iacResourceTypeVOMock;
37+
38+
private IacResourceTypeResponse getExpectedIacResourceTypeResponse() {
39+
IacResourceTypeResponse iacResourceTypeResponse = new IacResourceTypeResponse();
40+
iacResourceTypeResponse.setId("uuid");
41+
iacResourceTypeResponse.setName("Resource Type Name");
42+
iacResourceTypeResponse.setIacResourceTypeContent("node_type: ResourceTypeName");
43+
return iacResourceTypeResponse;
44+
}
45+
46+
@Test
47+
public void createIacResourceTypeResponseTestShouldPopulateAllFieldsOfTheResponse() {
48+
IacResourceTypeResponse expected = getExpectedIacResourceTypeResponse();
49+
50+
Mockito.when(iacResourceTypeVOMock.getUuid()).thenReturn(expected.getId());
51+
Mockito.when(iacResourceTypeVOMock.getName()).thenReturn(expected.getName());
52+
Mockito.when(iacResourceTypeVOMock.getContent()).thenReturn(expected.getIacResourceTypeContent());
53+
54+
IacResourceTypeResponse actual = nimbleResponseBuilderSpy.createIacResourceTypeResponse(iacResourceTypeVOMock);
55+
Assert.assertEquals(expected.getId(), actual.getId());
56+
Assert.assertEquals(expected.getName(), actual.getName());
57+
Assert.assertEquals(expected.getIacResourceTypeContent(), actual.getIacResourceTypeContent());
58+
}
59+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package org.apache.cloudstack.service;
18+
19+
import com.cloud.utils.Pair;
20+
import org.apache.cloudstack.api.command.ListIacResourceTypesCmd;
21+
import org.apache.cloudstack.api.response.IacResourceTypeResponse;
22+
import org.apache.cloudstack.api.response.ListResponse;
23+
import org.apache.cloudstack.api.response.NimbleResponseBuilder;
24+
import org.apache.cloudstack.persistence.iactemplatesprofile.IacResourceTypeDao;
25+
import org.apache.cloudstack.persistence.iactemplatesprofile.IacResourceTypeVO;
26+
import org.apache.cloudstack.tosca.model.ToscaNodeType;
27+
import org.apache.cloudstack.tosca.parser.ToscaParser;
28+
import org.junit.Assert;
29+
import org.junit.Test;
30+
import org.junit.runner.RunWith;
31+
import org.mockito.InjectMocks;
32+
import org.mockito.Mock;
33+
import org.mockito.Mockito;
34+
import org.mockito.Spy;
35+
import org.mockito.junit.MockitoJUnitRunner;
36+
37+
import java.util.List;
38+
import java.util.Map;
39+
40+
@RunWith(MockitoJUnitRunner.class)
41+
public class NimbleManagerImplTest {
42+
@Spy
43+
@InjectMocks
44+
private NimbleManagerImpl nimbleServiceSpy;
45+
46+
@Mock
47+
private ListIacResourceTypesCmd listIacResourceTypesCmdMock;
48+
49+
@Mock
50+
private IacResourceTypeDao iacResourceTypeDaoMock;
51+
52+
@Mock
53+
private NimbleResponseBuilder nimbleResponseBuilderMock;
54+
55+
@Mock
56+
private ToscaParser toscaParserMock;
57+
58+
@Test
59+
public void listIacResourceTypesTestShouldGenerateAResponseForEachIacResourceType() {
60+
long iacResourceTypeId = 1L;
61+
String iacResourceTypeName = "Iac Resource Type Name";
62+
String iacResourceTypeKeyword = "Iac Resource Type Keyword";
63+
long pageSize = 5L;
64+
long startIndex = 1L;
65+
66+
Mockito.when(listIacResourceTypesCmdMock.getId()).thenReturn(iacResourceTypeId);
67+
Mockito.when(listIacResourceTypesCmdMock.getName()).thenReturn(iacResourceTypeName);
68+
Mockito.when(listIacResourceTypesCmdMock.getKeyword()).thenReturn(iacResourceTypeKeyword);
69+
Mockito.when(listIacResourceTypesCmdMock.getPageSizeVal()).thenReturn(pageSize);
70+
Mockito.when(listIacResourceTypesCmdMock.getStartIndex()).thenReturn(startIndex);
71+
72+
List<IacResourceTypeVO> iacResourceTypesMock = List.of(Mockito.mock(IacResourceTypeVO.class), Mockito.mock(IacResourceTypeVO.class));
73+
Mockito.when(iacResourceTypeDaoMock.listIacResourceTypes(Mockito.eq(iacResourceTypeId), Mockito.eq(iacResourceTypeName),
74+
Mockito.eq(iacResourceTypeKeyword), Mockito.eq(pageSize), Mockito.eq(startIndex)))
75+
.thenReturn(new Pair<>(iacResourceTypesMock, iacResourceTypesMock.size()));
76+
77+
List<IacResourceTypeResponse> iacResourceTypeResponsesMock = List.of(Mockito.mock(IacResourceTypeResponse.class), Mockito.mock(IacResourceTypeResponse.class));
78+
for (int i = 0; i < iacResourceTypesMock.size(); i++) {
79+
Mockito.when(nimbleResponseBuilderMock.createIacResourceTypeResponse(Mockito.eq(iacResourceTypesMock.get(i))))
80+
.thenReturn(iacResourceTypeResponsesMock.get(i));
81+
}
82+
83+
ListResponse<IacResourceTypeResponse> response = nimbleServiceSpy.listIacResourceTypes(listIacResourceTypesCmdMock);
84+
for (IacResourceTypeVO iacResourceType : iacResourceTypesMock) {
85+
Mockito.verify(nimbleResponseBuilderMock).createIacResourceTypeResponse(Mockito.eq(iacResourceType));
86+
}
87+
Assert.assertEquals(iacResourceTypeResponsesMock, response.getResponses());
88+
Assert.assertEquals(iacResourceTypeResponsesMock.size(), response.getCount().intValue());
89+
}
90+
91+
@Test
92+
public void loadToscaProfileTestEachIacResourceTypeShouldBeParsed() {
93+
String firstIacResourceTypeName = "First Iac Resource Type Name";
94+
String secondIacResourceTypeName = "Second Iac Resource Type Name";
95+
96+
List<IacResourceTypeVO> iacResourceTypesMock = List.of(Mockito.mock(IacResourceTypeVO.class), Mockito.mock(IacResourceTypeVO.class));
97+
Mockito.when(iacResourceTypesMock.get(0).getName()).thenReturn(firstIacResourceTypeName);
98+
Mockito.when(iacResourceTypesMock.get(1).getName()).thenReturn(secondIacResourceTypeName);
99+
100+
Mockito.when(iacResourceTypeDaoMock.listAll()).thenReturn(iacResourceTypesMock);
101+
102+
List<ToscaNodeType> toscaNodeTypesMock = List.of(Mockito.mock(ToscaNodeType.class), Mockito.mock(ToscaNodeType.class));
103+
Mockito.when(toscaNodeTypesMock.get(0).getName()).thenReturn("First TOSCA node type");
104+
Mockito.when(toscaNodeTypesMock.get(1).getName()).thenReturn("Second TOSCA node type");
105+
106+
Mockito.when(toscaParserMock.parseNodeType(Mockito.eq(firstIacResourceTypeName), Mockito.any())).thenReturn(toscaNodeTypesMock.get(0));
107+
Mockito.when(toscaParserMock.parseNodeType(Mockito.eq(secondIacResourceTypeName), Mockito.any())).thenReturn(toscaNodeTypesMock.get(1));
108+
109+
Map<String, ToscaNodeType> profile = nimbleServiceSpy.loadToscaProfile();
110+
Mockito.verify(toscaParserMock, Mockito.times(iacResourceTypesMock.size())).parseNodeType(Mockito.any(), Mockito.any());
111+
Assert.assertEquals(iacResourceTypesMock.size(), profile.size());
112+
for (ToscaNodeType toscaNodeType : toscaNodeTypesMock) {
113+
Assert.assertTrue(profile.containsKey(toscaNodeType.getName()));
114+
}
115+
}
116+
}

0 commit comments

Comments
 (0)