Просмотр исходного кода

Merge branch 'beta.3.integration-frontend' of https://github.com/porter-dev/porter into sean-testing

Sean Rhee 5 лет назад
Родитель
Сommit
7a0f95dcd6
2 измененных файлов с 146 добавлено и 13 удалено
  1. 115 12
      dashboard/src/main/home/new-project/NewProject.tsx
  2. 31 1
      dashboard/src/shared/api.tsx

+ 115 - 12
dashboard/src/main/home/new-project/NewProject.tsx

@@ -26,6 +26,9 @@ type StateType = {
   awsRegion: string | null,
   awsAccessId: string | null,
   awsSecretKey: string | null,
+  gcpRegion: string | null,
+  gcpProjectId: string | null,
+  gcpKeyData: string | null,
   status: string | null,
 };
 
@@ -37,6 +40,9 @@ export default class NewProject extends Component<PropsType, StateType> {
     awsRegion: '' as string | null,
     awsAccessId: '' as string | null,
     awsSecretKey: '' as string | null,
+    gcpRegion: '' as string | null,
+    gcpProjectId: '' as string | null,
+    gcpKeyData: '' as string | null,
     status: null as string | null,
   }
 
@@ -52,11 +58,11 @@ export default class NewProject extends Component<PropsType, StateType> {
     this.setState({ selectedProvider: provider });
   }
 
-  renderTemplateList = () => {
+  renderProviderList = () => {
     return providers.map((provider: string, i: number) => {
       let providerInfo = integrationList[provider];
       return (
-        <Block 
+        <Block
           key={i} 
           onClick={() => this.handleSelectProvider(provider)}
         >
@@ -127,9 +133,41 @@ export default class NewProject extends Component<PropsType, StateType> {
           }}>
             <CloseButtonImg src={close} />
           </CloseButton>
-          <Flex>
-            GCP support is in closed beta. If you would like to run Porter in your own Google Cloud account, email <Highlight>contact@getporter.dev</Highlight>.
-          </Flex>
+          <DarkMatter />
+          <Heading>
+            GCP Credentials
+            <GuideButton href='https://docs.getporter.dev/docs/getting-started-with-porter-on-gcp' target='_blank'>
+              <i className="material-icons-outlined">help</i> 
+              Guide
+            </GuideButton>
+          </Heading>
+          <InputRow
+            type='text'
+            value={this.state.gcpRegion}
+            setValue={(x: string) => this.setState({ gcpRegion: x })}
+            label='📍 GCP Region'
+            placeholder='ex: us-central1-a'
+            width='100%'
+            isRequired={true}
+          />
+          <InputRow
+            type='text'
+            value={this.state.gcpProjectId}
+            setValue={(x: string) => this.setState({ gcpProjectId: x })}
+            label='🏷️ GCP Project ID'
+            placeholder='ex: pale-moon-24601'
+            width='100%'
+            isRequired={true}
+          />
+          <InputRow
+            type='password'
+            value={this.state.gcpKeyData}
+            setValue={(x: string) => this.setState({ gcpKeyData: x })}
+            label='🔒 GCP Key Data'
+            placeholder='○ ○ ○ ○ ○ ○ ○ ○ ○'
+            width='100%'
+            isRequired={true}
+          />
         </FormSection>
       );
     } else if (this.state.selectedProvider === 'do') {
@@ -149,7 +187,7 @@ export default class NewProject extends Component<PropsType, StateType> {
 
     return (
       <BlockList>
-        {this.renderTemplateList()}
+        {this.renderProviderList()}
       </BlockList>
     );
   }
@@ -195,12 +233,23 @@ export default class NewProject extends Component<PropsType, StateType> {
   }
 
   validateForm = () => {
-    let { projectName, selectedProvider, awsAccessId, awsSecretKey, awsRegion } = this.state;
+    let { 
+      projectName,
+      selectedProvider, 
+      awsAccessId, 
+      awsSecretKey, 
+      awsRegion,
+      gcpRegion,
+      gcpKeyData,
+      gcpProjectId,
+    } = this.state;
     if (!this.isAlphanumeric(projectName) || projectName === '') {
       return false;
     } else if (selectedProvider === 'aws') {
       return awsAccessId !== '' && awsSecretKey !== '' && awsRegion !== '';
-    }  else if (selectedProvider === 'skipped') {
+    } else if (selectedProvider === 'gcp') {
+      return gcpRegion !== '' && gcpKeyData !== '' && gcpProjectId !== '';
+    } else if (selectedProvider === 'skipped') {
       return true;
     }
     return false;
@@ -265,13 +314,64 @@ export default class NewProject extends Component<PropsType, StateType> {
         }
 
         this.props.setCurrentView('provisioner', [
-          {infra_id: ecr?.data?.id, kind: ecr?.data?.kind},
-          {infra_id: eks?.data?.id, kind: eks?.data?.kind},
+          { infra_id: ecr?.data?.id, kind: ecr?.data?.kind },
+          { infra_id: eks?.data?.id, kind: eks?.data?.kind },
         ]);
       })
     })
   }
 
+  provisionGKE = (proj: ProjectType, id: number) => {
+    let clusterName = `${proj.name}-cluster`
+    console.log('provisioning gke...');
+    api.createGKE('<token>', {
+      gke_name: clusterName,
+      gcp_integration_id: id,
+    }, { project_id: proj.id }, (err: any, res: any) => {
+      if (err) {
+        console.log(err);
+      } else if (res?.data) {
+        
+        // TODO: set to provisioner
+        alert('success');
+      }
+    });
+  }
+
+  provisionGCR = (proj: ProjectType, id: number) => {
+    console.log('provisioning gcr...');
+    api.createGCR('<token>', {
+      gcp_integration_id: id,
+    }, { project_id: proj.id }, (err: any, res: any) => {
+      if (err) {
+        console.log(err);
+      } else if (res?.data) {
+        console.log('gcr provisioned with response: ', res.data);
+        this.provisionGKE(proj, id);
+      }
+    });
+  }
+
+  provisionGCP = (proj: ProjectType) => {
+    this.setState({ status: 'loading' });
+
+    let { gcpRegion, gcpKeyData, gcpProjectId } = this.state;
+    console.log('provisioning gcp...');
+    api.createGCPIntegration('<token>', {
+      gcp_region: gcpRegion,
+      gcp_key_data: gcpKeyData,
+      gcp_project_id: gcpProjectId,
+    }, { project_id: proj.id }, (err: any, res: any) => {
+      if (err) {
+        console.log(err);
+      } else if (res?.data) {
+        console.log('gcp provisioned with response: ', res.data);
+        let { id } = res.data;
+        this.provisionGCR(proj, id);
+      }
+    });
+  }
+
   createProject = () => {
     this.setState({ status: 'loading' });
     api.createProject('<token>', {
@@ -291,7 +391,9 @@ export default class NewProject extends Component<PropsType, StateType> {
               this.context.setCurrentProject(proj);
               
               if (this.state.selectedProvider === 'aws') {
-                this.provisionECR(proj, this.provisionEKS)
+                this.provisionECR(proj, this.provisionEKS);
+              } else if (this.state.selectedProvider === 'gcp') { 
+                this.provisionGCP(proj);
               } else {
                 this.props.setCurrentView('dashboard', null);
               }
@@ -406,8 +508,9 @@ export default class NewProject extends Component<PropsType, StateType> {
   }
   
   render() {
+    let { selectedProvider } = this.state;
     return (
-      <StyledNewProject height={this.state.selectedProvider === 'aws' ? '700px' : '600px'}>
+      <StyledNewProject height={selectedProvider === 'aws' || selectedProvider === 'gcp' ? '700px' : '600px'}>
         {this.renderHeaderSection()}
         {this.renderHostingSection()}
         {this.renderButton()}

+ 31 - 1
dashboard/src/shared/api.tsx

@@ -291,10 +291,40 @@ const deleteCluster = baseApi<{
   cluster_id: number,
 }>('DELETE', pathParams => {
   return `/api/projects/${pathParams.project_id}/clusters/${pathParams.cluster_id}`;
-})
+});
+
+const createGCPIntegration = baseApi<{
+  gcp_region: string,
+  gcp_key_data: string,
+  gcp_project_id: string,
+}, {
+  project_id: number,
+}>('POST', pathParams => {
+  return `/api/projects/${pathParams.project_id}/integrations/gcp`;
+});
+
+const createGCR = baseApi<{
+  gcp_integration_id: number,
+}, {
+  project_id: number,
+}>('POST', pathParams => {
+  return `/api/projects/${pathParams.project_id}/provision/gcr`;
+});
+
+const createGKE = baseApi<{
+  gcp_integration_id: number,
+  gke_name: string,
+}, {
+  project_id: number,
+}>('POST', pathParams => {
+  return `/api/projects/${pathParams.project_id}/provision/gke`;
+});
 
 // Bundle export to allow default api import (api.<method> is more readable)
 export default {
+  createGCR,
+  createGKE,
+  createGCPIntegration,
   deleteCluster,
   destroyCluster,
   getInfra,