Generalization of controller
[nonrtric.git] / policy-agent / src / main / java / org / oransc / policyagent / clients / SdncOscA1Client.java
1 /*-
2  * ========================LICENSE_START=================================
3  * O-RAN-SC
4  * %%
5  * Copyright (C) 2020 Nordix Foundation
6  * %%
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ========================LICENSE_END===================================
19  */
20
21 package org.oransc.policyagent.clients;
22
23 import com.google.gson.FieldNamingPolicy;
24 import com.google.gson.GsonBuilder;
25
26 import java.lang.invoke.MethodHandles;
27 import java.nio.charset.StandardCharsets;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Optional;
31
32 import org.immutables.value.Value;
33 import org.oransc.policyagent.configuration.RicConfig;
34 import org.oransc.policyagent.repository.Policy;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.springframework.http.HttpStatus;
38 import org.springframework.web.reactive.function.client.WebClientResponseException;
39
40 import reactor.core.publisher.Flux;
41 import reactor.core.publisher.Mono;
42
43 @SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
44 public class SdncOscA1Client implements A1Client {
45
46     @Value.Immutable
47     @org.immutables.gson.Gson.TypeAdapters
48     public interface AdapterRequest {
49         public String nearRtRicUrl();
50
51         public Optional<String> body();
52     }
53
54     @Value.Immutable
55     @org.immutables.gson.Gson.TypeAdapters
56     public interface AdapterResponse {
57         public String body();
58
59         public int httpStatus();
60     }
61
62     static com.google.gson.Gson gson = new GsonBuilder() //
63         .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) //
64         .create(); //
65
66     private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
67     private final String a1ControllerUsername;
68     private final String a1ControllerPassword;
69     private final AsyncRestClient restClient;
70     private final A1UriBuilder uri;
71
72     public SdncOscA1Client(RicConfig ricConfig, String controllerBaseUrl, String username, String password) {
73         this(ricConfig, username, password, new AsyncRestClient(controllerBaseUrl + "/restconf/operations"));
74         logger.debug("SdncOscA1Client for ric: {}, a1ControllerBaseUrl: {}", ricConfig.name(), controllerBaseUrl);
75     }
76
77     public SdncOscA1Client(RicConfig ricConfig, String username, String password, AsyncRestClient restClient) {
78         this.a1ControllerUsername = username;
79         this.a1ControllerPassword = password;
80         this.restClient = restClient;
81         this.uri = new StdA1UriBuilderVersion1(ricConfig);
82     }
83
84     @Override
85     public Mono<List<String>> getPolicyTypeIdentities() {
86         return Mono.just(Arrays.asList(""));
87     }
88
89     @Override
90     public Mono<List<String>> getPolicyIdentities() {
91         return getPolicyIds() //
92             .collectList();
93     }
94
95     @Override
96     public Mono<String> getPolicyTypeSchema(String policyTypeId) {
97         return Mono.just("{}");
98     }
99
100     @Override
101     public Mono<String> putPolicy(Policy policy) {
102         final String ricUrl = uri.createPutPolicyUri(policy);
103         return post("putA1Policy", ricUrl, Optional.of(policy.json()));
104     }
105
106     @Override
107     public Mono<String> deletePolicy(Policy policy) {
108         return deletePolicyById(policy.id());
109     }
110
111     @Override
112     public Flux<String> deleteAllPolicies() {
113         return getPolicyIds() //
114             .flatMap(this::deletePolicyById); //
115     }
116
117     @Override
118     public Mono<A1ProtocolType> getProtocolVersion() {
119         return getPolicyIdentities() //
120             .flatMap(x -> Mono.just(A1ProtocolType.SDNC_OSC));
121     }
122
123     @Override
124     public Mono<String> getPolicyStatus(Policy policy) {
125         final String ricUrl = uri.createGetPolicyStatusUri(policy.id());
126         return post("getA1PolicyStatus", ricUrl, Optional.empty());
127     }
128
129     private Flux<String> getPolicyIds() {
130         final String ricUrl = uri.createGetPolicyIdsUri();
131         return post("getA1Policy", ricUrl, Optional.empty()) //
132             .flatMapMany(JsonHelper::parseJsonArrayOfString);
133     }
134
135     private Mono<String> deletePolicyById(String policyId) {
136         final String ricUrl = uri.createDeleteUri(policyId);
137         return post("deleteA1Policy", ricUrl, Optional.empty());
138     }
139
140     private Mono<String> post(String rpcName, String ricUrl, Optional<String> body) {
141         AdapterRequest inputParams = ImmutableAdapterRequest.builder() //
142             .nearRtRicUrl(ricUrl) //
143             .body(body) //
144             .build();
145         final String inputJsonString = JsonHelper.createInputJsonString(inputParams);
146
147         return restClient
148             .postWithAuthHeader(controllerUrl(rpcName), inputJsonString, a1ControllerUsername, a1ControllerPassword)
149             .flatMap(this::extractResponseBody);
150     }
151
152     private Mono<String> extractResponseBody(String response) {
153         AdapterResponse output = gson.fromJson(response, ImmutableAdapterResponse.class);
154         String body = output.body();
155         if (HttpStatus.valueOf(output.httpStatus()).is2xxSuccessful()) {
156             return Mono.just(body);
157         }
158         byte[] responseBodyBytes = body.getBytes(StandardCharsets.UTF_8);
159         WebClientResponseException e = new WebClientResponseException(output.httpStatus(), "statusText", null,
160             responseBodyBytes, StandardCharsets.UTF_8, null);
161
162         return Mono.error(e);
163     }
164
165     private String controllerUrl(String rpcName) {
166         return "/A1-ADAPTER-API:" + rpcName;
167     }
168 }