1   /*
2    * Copyright 2017 LINE Corporation
3    *
4    * LINE Corporation licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://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, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package com.linecorp.centraldogma.server.internal.storage.project;
18  
19  import static com.linecorp.centraldogma.server.command.Command.createProject;
20  import static com.linecorp.centraldogma.server.command.Command.createRepository;
21  import static com.linecorp.centraldogma.server.command.Command.push;
22  
23  import java.util.List;
24  
25  import com.google.common.collect.ImmutableList;
26  
27  import com.linecorp.armeria.common.util.Exceptions;
28  import com.linecorp.centraldogma.common.Author;
29  import com.linecorp.centraldogma.common.Change;
30  import com.linecorp.centraldogma.common.ChangeConflictException;
31  import com.linecorp.centraldogma.common.Markup;
32  import com.linecorp.centraldogma.common.ProjectExistsException;
33  import com.linecorp.centraldogma.common.RepositoryExistsException;
34  import com.linecorp.centraldogma.common.Revision;
35  import com.linecorp.centraldogma.internal.Jackson;
36  import com.linecorp.centraldogma.server.command.CommandExecutor;
37  import com.linecorp.centraldogma.server.metadata.MetadataService;
38  import com.linecorp.centraldogma.server.metadata.Tokens;
39  import com.linecorp.centraldogma.server.storage.project.Project;
40  
41  public final class ProjectInitializer {
42  
43      public static final String INTERNAL_PROJECT_DOGMA = "dogma";
44  
45      /**
46       * Creates an internal project and repositories such as a token storage.
47       */
48      public static void initializeInternalProject(CommandExecutor executor) {
49          final long creationTimeMillis = System.currentTimeMillis();
50          initializeInternalProject(executor, creationTimeMillis, INTERNAL_PROJECT_DOGMA);
51  
52          // These repositories might be created when creating an internal project, but we try to create them
53          // again here in order to make sure them exist because sometimes their names are changed.
54          initializeInternalRepos(executor, creationTimeMillis, Project.internalRepos());
55  
56          try {
57              final Change<?> change = Change.ofJsonPatch(MetadataService.TOKEN_JSON,
58                                                          null, Jackson.valueToTree(new Tokens()));
59              final String commitSummary = "Initialize the token list file: /" + INTERNAL_PROJECT_DOGMA + '/' +
60                                           Project.REPO_DOGMA + MetadataService.TOKEN_JSON;
61              executor.execute(push(Author.SYSTEM, INTERNAL_PROJECT_DOGMA, Project.REPO_DOGMA, Revision.HEAD,
62                                    commitSummary, "", Markup.PLAINTEXT, ImmutableList.of(change)))
63                      .get();
64          } catch (Throwable cause) {
65              final Throwable peeled = Exceptions.peel(cause);
66              if (!(peeled instanceof ChangeConflictException)) {
67                  throw new Error("failed to initialize the token list file", peeled);
68              }
69          }
70      }
71  
72      public static void initializeInternalProject(
73              CommandExecutor executor, long creationTimeMillis, String projectName) {
74          try {
75              executor.execute(createProject(creationTimeMillis, Author.SYSTEM, projectName))
76                      .get();
77          } catch (Throwable cause) {
78              final Throwable peeled = Exceptions.peel(cause);
79              if (!(peeled instanceof ProjectExistsException)) {
80                  throw new Error("failed to initialize an internal project: " + projectName, peeled);
81              }
82          }
83      }
84  
85      public static void initializeInternalRepos(
86              CommandExecutor executor, long creationTimeMillis, List<String> internalRepos) {
87          for (final String repo : internalRepos) {
88              try {
89                  executor.execute(createRepository(creationTimeMillis, Author.SYSTEM,
90                                                    INTERNAL_PROJECT_DOGMA, repo))
91                          .get();
92              } catch (Throwable cause) {
93                  final Throwable peeled = Exceptions.peel(cause);
94                  if (!(peeled instanceof RepositoryExistsException)) {
95                      throw new Error("failed to initialize an internal repository: " + INTERNAL_PROJECT_DOGMA +
96                                      '/' + repo, peeled);
97                  }
98              }
99          }
100     }
101 
102     private ProjectInitializer() {}
103 }