• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google LLC
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.google.cloud.dns;
18 
19 import static com.google.cloud.RetryHelper.runWithRetries;
20 import static com.google.common.base.Preconditions.checkArgument;
21 
22 import com.google.api.gax.paging.Page;
23 import com.google.api.services.dns.model.Change;
24 import com.google.api.services.dns.model.ManagedZone;
25 import com.google.api.services.dns.model.Project;
26 import com.google.api.services.dns.model.ResourceRecordSet;
27 import com.google.cloud.BaseService;
28 import com.google.cloud.PageImpl;
29 import com.google.cloud.RetryHelper;
30 import com.google.cloud.dns.spi.v1.DnsRpc;
31 import com.google.common.base.Function;
32 import com.google.common.collect.ImmutableList;
33 import com.google.common.collect.ImmutableMap;
34 import com.google.common.collect.Iterables;
35 import com.google.common.collect.Maps;
36 import java.util.Map;
37 import java.util.concurrent.Callable;
38 
39 /** A default implementation of Dns. */
40 final class DnsImpl extends BaseService<DnsOptions> implements Dns {
41 
42   private final DnsRpc dnsRpc;
43 
44   static class ZonePageFetcher implements PageImpl.NextPageFetcher<Zone> {
45 
46     private static final long serialVersionUID = 2158209410430566961L;
47     private final Map<DnsRpc.Option, ?> requestOptions;
48     private final DnsOptions serviceOptions;
49 
ZonePageFetcher(DnsOptions serviceOptions, String cursor, Map<DnsRpc.Option, ?> optionMap)50     ZonePageFetcher(DnsOptions serviceOptions, String cursor, Map<DnsRpc.Option, ?> optionMap) {
51       this.requestOptions =
52           PageImpl.nextRequestOptions(DnsRpc.Option.PAGE_TOKEN, cursor, optionMap);
53       this.serviceOptions = serviceOptions;
54     }
55 
56     @Override
getNextPage()57     public Page<Zone> getNextPage() {
58       return listZones(serviceOptions, requestOptions);
59     }
60   }
61 
62   static class ChangeRequestPageFetcher implements PageImpl.NextPageFetcher<ChangeRequest> {
63 
64     private static final long serialVersionUID = 4473265130673029139L;
65     private final String zoneName;
66     private final Map<DnsRpc.Option, ?> requestOptions;
67     private final DnsOptions serviceOptions;
68 
ChangeRequestPageFetcher( String zoneName, DnsOptions serviceOptions, String cursor, Map<DnsRpc.Option, ?> optionMap)69     ChangeRequestPageFetcher(
70         String zoneName,
71         DnsOptions serviceOptions,
72         String cursor,
73         Map<DnsRpc.Option, ?> optionMap) {
74       this.zoneName = zoneName;
75       this.requestOptions =
76           PageImpl.nextRequestOptions(DnsRpc.Option.PAGE_TOKEN, cursor, optionMap);
77       this.serviceOptions = serviceOptions;
78     }
79 
80     @Override
getNextPage()81     public Page<ChangeRequest> getNextPage() {
82       return listChangeRequests(zoneName, serviceOptions, requestOptions);
83     }
84   }
85 
86   static class RecordSetPageFetcher implements PageImpl.NextPageFetcher<RecordSet> {
87 
88     private static final long serialVersionUID = -6039369212511530846L;
89     private final Map<DnsRpc.Option, ?> requestOptions;
90     private final DnsOptions serviceOptions;
91     private final String zoneName;
92 
RecordSetPageFetcher( String zoneName, DnsOptions serviceOptions, String cursor, Map<DnsRpc.Option, ?> optionMap)93     RecordSetPageFetcher(
94         String zoneName,
95         DnsOptions serviceOptions,
96         String cursor,
97         Map<DnsRpc.Option, ?> optionMap) {
98       this.zoneName = zoneName;
99       this.requestOptions =
100           PageImpl.nextRequestOptions(DnsRpc.Option.PAGE_TOKEN, cursor, optionMap);
101       this.serviceOptions = serviceOptions;
102     }
103 
104     @Override
getNextPage()105     public Page<RecordSet> getNextPage() {
106       return listRecordSets(zoneName, serviceOptions, requestOptions);
107     }
108   }
109 
DnsImpl(DnsOptions options)110   DnsImpl(DnsOptions options) {
111     super(options);
112     dnsRpc = options.getDnsRpcV1();
113   }
114 
zoneFromPb(final DnsOptions options)115   static Function<ManagedZone, Zone> zoneFromPb(final DnsOptions options) {
116     return new Function<ManagedZone, Zone>() {
117       @Override
118       public Zone apply(ManagedZone zonePb) {
119         return Zone.fromPb(options.getService(), zonePb);
120       }
121     };
122   }
123 
124   @Override
125   public Page<Zone> listZones(ZoneListOption... options) {
126     return listZones(getOptions(), optionMap(options));
127   }
128 
129   private static Page<Zone> listZones(
130       final DnsOptions serviceOptions, final Map<DnsRpc.Option, ?> optionsMap) {
131     try {
132       // get a list of managed zones
133       final DnsRpc rpc = serviceOptions.getDnsRpcV1();
134       DnsRpc.ListResult<ManagedZone> result =
135           runWithRetries(
136               new Callable<DnsRpc.ListResult<ManagedZone>>() {
137                 @Override
138                 public DnsRpc.ListResult<ManagedZone> call() {
139                   return rpc.listZones(optionsMap);
140                 }
141               },
142               serviceOptions.getRetrySettings(),
143               EXCEPTION_HANDLER,
144               serviceOptions.getClock());
145       String cursor = result.pageToken();
146       // transform that list into zone objects
147       Iterable<Zone> zones =
148           result.results() == null
149               ? ImmutableList.<Zone>of()
150               : Iterables.transform(result.results(), zoneFromPb(serviceOptions));
151       return new PageImpl<>(new ZonePageFetcher(serviceOptions, cursor, optionsMap), cursor, zones);
152     } catch (RetryHelper.RetryHelperException e) {
153       throw DnsException.translateAndThrow(e);
154     }
155   }
156 
157   @Override
158   public Page<ChangeRequest> listChangeRequests(
159       String zoneName, ChangeRequestListOption... options) {
160     return listChangeRequests(zoneName, getOptions(), optionMap(options));
161   }
162 
163   private static Page<ChangeRequest> listChangeRequests(
164       final String zoneName,
165       final DnsOptions serviceOptions,
166       final Map<DnsRpc.Option, ?> optionsMap) {
167     try {
168       // get a list of changes
169       final DnsRpc rpc = serviceOptions.getDnsRpcV1();
170       DnsRpc.ListResult<Change> result =
171           runWithRetries(
172               new Callable<DnsRpc.ListResult<Change>>() {
173                 @Override
174                 public DnsRpc.ListResult<Change> call() {
175                   return rpc.listChangeRequests(zoneName, optionsMap);
176                 }
177               },
178               serviceOptions.getRetrySettings(),
179               EXCEPTION_HANDLER,
180               serviceOptions.getClock());
181       String cursor = result.pageToken();
182       // transform that list into change request objects
183       Iterable<ChangeRequest> changes =
184           result.results() == null
185               ? ImmutableList.<ChangeRequest>of()
186               : Iterables.transform(
187                   result.results(),
188                   ChangeRequest.fromPbFunction(serviceOptions.getService(), zoneName));
189       return new PageImpl<>(
190           new ChangeRequestPageFetcher(zoneName, serviceOptions, cursor, optionsMap),
191           cursor,
192           changes);
193     } catch (RetryHelper.RetryHelperException e) {
194       throw DnsException.translateAndThrow(e);
195     }
196   }
197 
198   @Override
199   public Page<RecordSet> listRecordSets(String zoneName, RecordSetListOption... options) {
200     return listRecordSets(zoneName, getOptions(), optionMap(options));
201   }
202 
203   private static Page<RecordSet> listRecordSets(
204       final String zoneName,
205       final DnsOptions serviceOptions,
206       final Map<DnsRpc.Option, ?> optionsMap) {
207     try {
208       // get a list of record sets
209       final DnsRpc rpc = serviceOptions.getDnsRpcV1();
210       DnsRpc.ListResult<ResourceRecordSet> result =
211           runWithRetries(
212               new Callable<DnsRpc.ListResult<ResourceRecordSet>>() {
213                 @Override
214                 public DnsRpc.ListResult<ResourceRecordSet> call() {
215                   return rpc.listRecordSets(zoneName, optionsMap);
216                 }
217               },
218               serviceOptions.getRetrySettings(),
219               EXCEPTION_HANDLER,
220               serviceOptions.getClock());
221       String cursor = result.pageToken();
222       // transform that list into record sets
223       Iterable<RecordSet> recordSets =
224           result.results() == null
225               ? ImmutableList.<RecordSet>of()
226               : Iterables.transform(result.results(), RecordSet.FROM_PB_FUNCTION);
227       return new PageImpl<>(
228           new RecordSetPageFetcher(zoneName, serviceOptions, cursor, optionsMap),
229           cursor,
230           recordSets);
231     } catch (RetryHelper.RetryHelperException e) {
232       throw DnsException.translateAndThrow(e);
233     }
234   }
235 
236   @Override
237   public Zone create(final ZoneInfo zoneInfo, Dns.ZoneOption... options) {
238     final Map<DnsRpc.Option, ?> optionsMap = optionMap(options);
239     try {
240       ManagedZone answer =
241           runWithRetries(
242               new Callable<ManagedZone>() {
243                 @Override
244                 public ManagedZone call() {
245                   return dnsRpc.create(zoneInfo.toPb(), optionsMap);
246                 }
247               },
248               getOptions().getRetrySettings(),
249               EXCEPTION_HANDLER,
250               getOptions().getClock());
251       return answer == null ? null : Zone.fromPb(this, answer);
252     } catch (RetryHelper.RetryHelperException ex) {
253       throw DnsException.translateAndThrow(ex);
254     }
255   }
256 
257   @Override
258   public Zone getZone(final String zoneName, Dns.ZoneOption... options) {
259     final Map<DnsRpc.Option, ?> optionsMap = optionMap(options);
260     try {
261       ManagedZone answer =
262           runWithRetries(
263               new Callable<ManagedZone>() {
264                 @Override
265                 public ManagedZone call() {
266                   return dnsRpc.getZone(zoneName, optionsMap);
267                 }
268               },
269               getOptions().getRetrySettings(),
270               EXCEPTION_HANDLER,
271               getOptions().getClock());
272       return answer == null ? null : Zone.fromPb(this, answer);
273     } catch (RetryHelper.RetryHelperException ex) {
274       throw DnsException.translateAndThrow(ex);
275     }
276   }
277 
278   @Override
279   public boolean delete(final String zoneName) {
280     try {
281       return runWithRetries(
282           new Callable<Boolean>() {
283             @Override
284             public Boolean call() {
285               return dnsRpc.deleteZone(zoneName);
286             }
287           },
288           getOptions().getRetrySettings(),
289           EXCEPTION_HANDLER,
290           getOptions().getClock());
291     } catch (RetryHelper.RetryHelperException ex) {
292       throw DnsException.translateAndThrow(ex);
293     }
294   }
295 
296   @Override
297   public ProjectInfo getProject(Dns.ProjectOption... fields) {
298     final Map<DnsRpc.Option, ?> optionsMap = optionMap(fields);
299     try {
300       Project answer =
301           runWithRetries(
302               new Callable<Project>() {
303                 @Override
304                 public Project call() {
305                   return dnsRpc.getProject(optionsMap);
306                 }
307               },
308               getOptions().getRetrySettings(),
309               EXCEPTION_HANDLER,
310               getOptions().getClock());
311       return answer == null ? null : ProjectInfo.fromPb(answer); // should never be null
312     } catch (RetryHelper.RetryHelperException ex) {
313       throw DnsException.translateAndThrow(ex);
314     }
315   }
316 
317   @Override
318   public ChangeRequest applyChangeRequest(
319       final String zoneName,
320       final ChangeRequestInfo changeRequest,
321       ChangeRequestOption... options) {
322     final Map<DnsRpc.Option, ?> optionsMap = optionMap(options);
323     try {
324       Change answer =
325           runWithRetries(
326               new Callable<Change>() {
327                 @Override
328                 public Change call() {
329                   return dnsRpc.applyChangeRequest(zoneName, changeRequest.toPb(), optionsMap);
330                 }
331               },
332               getOptions().getRetrySettings(),
333               EXCEPTION_HANDLER,
334               getOptions().getClock());
335       return answer == null ? null : ChangeRequest.fromPb(this, zoneName, answer); // not null
336     } catch (RetryHelper.RetryHelperException ex) {
337       throw DnsException.translateAndThrow(ex);
338     }
339   }
340 
341   @Override
342   public ChangeRequest getChangeRequest(
343       final String zoneName, final String changeRequestId, Dns.ChangeRequestOption... options) {
344     final Map<DnsRpc.Option, ?> optionsMap = optionMap(options);
345     try {
346       Change answer =
347           runWithRetries(
348               new Callable<Change>() {
349                 @Override
350                 public Change call() {
351                   return dnsRpc.getChangeRequest(zoneName, changeRequestId, optionsMap);
352                 }
353               },
354               getOptions().getRetrySettings(),
355               EXCEPTION_HANDLER,
356               getOptions().getClock());
357       return answer == null ? null : ChangeRequest.fromPb(this, zoneName, answer);
358     } catch (RetryHelper.RetryHelperException ex) {
359       throw DnsException.translateAndThrow(ex);
360     }
361   }
362 
363   @Override
364   public DnsBatch batch() {
365     return new DnsBatch(this.getOptions());
366   }
367 
368   static Map<DnsRpc.Option, ?> optionMap(Option... options) {
369     Map<DnsRpc.Option, Object> temp = Maps.newEnumMap(DnsRpc.Option.class);
370     for (Option option : options) {
371       Object prev = temp.put(option.getRpcOption(), option.getValue());
372       checkArgument(prev == null, "Duplicate option %s", option);
373     }
374     return ImmutableMap.copyOf(temp);
375   }
376 }
377