jusrhee пре 5 година
родитељ
комит
cdc2633ece

+ 2 - 0
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedChart.tsx

@@ -86,9 +86,11 @@ export default class ExpandedChart extends Component<PropsType, StateType> {
     for (const file of files) { 
       if (file.name === 'form.yaml') {
         let formData = yaml.load(Base64.decode(file.data));
+        /*
         if (this.props.currentChart.config) {
           console.log(formData)
         }
+        */
         return formData;
       }
     };

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/expanded-chart/status/ControllerTab.tsx

@@ -59,7 +59,7 @@ export default class ControllerTab extends Component<PropsType, StateType> {
           phase: pod?.status?.phase,
         }
       });
-      console.log(res.data);
+      // console.log(res.data);
       this.setState({ pods, raw: res.data });
     })
   }

+ 6 - 5
dashboard/src/main/home/integrations/IntegrationList.tsx

@@ -7,7 +7,7 @@ import api from '../../../shared/api';
 
 type PropsType = {
   setCurrent: (x: any) => void,
-  integrations: any,
+  integrations: string[],
   isCategory?: boolean
 };
 
@@ -18,9 +18,10 @@ export default class IntegrationList extends Component<PropsType, StateType> {
   renderContents = () => {
     let { integrations, setCurrent, isCategory } = this.props;
     if (integrations && integrations.length > 0) {
-      return integrations.map((integration: any, i: number) => {
-        let icon = integrationList[integration.value] && integrationList[integration.value].icon;
-        let disabled = integration.value === 'repo';
+      return integrations.map((integration: string, i: number) => {
+        let icon = integrationList[integration] && integrationList[integration].icon;
+        let label = integrationList[integration] && integrationList[integration].label;
+        let disabled = integration === 'repo' || integration === 'kubernetes';
         return (
           <Integration
             key={i}
@@ -30,7 +31,7 @@ export default class IntegrationList extends Component<PropsType, StateType> {
           >
             <Flex>
               <Icon src={icon && icon} />
-              <Label>{integration.label}</Label>
+              <Label>{label}</Label>
             </Flex>
             <i className="material-icons">{isCategory ? 'launch' : 'more_vert'}</i>
           </Integration>

+ 97 - 60
dashboard/src/main/home/integrations/Integrations.tsx

@@ -13,90 +13,93 @@ type PropsType = {
 };
 
 type StateType = {
-  currentCategory: ChoiceType | null,
+  currentCategory: string | null,
   currentIntegration: string | null,
   currentOptions: any[],
+  currentIntegrationData: any[],
 };
 
-const categories = [
-  {
-    value: 'kubernetes',
-    label: 'Kubernetes',
-    buttonText: 'Add a Cluster',
-  },
-  {
-    value: 'registry',
-    label: 'Docker Registry',
-    buttonText: 'Add a Registry',
-  },
-  {
-    value: 'repo',
-    label: 'Git Repository',
-    buttonText: 'Add a Repository',
-  },
-];
-
 export default class Integrations extends Component<PropsType, StateType> {
   state = {
-    currentCategory: null as any | null,
+    currentCategory: null as string | null,
     currentIntegration: null as string | null,
     currentOptions: [] as any[],
+    currentIntegrationData: [] as any[],
   }
 
   // TODO: implement once backend is restructured
-  getIntegrations = (categoryType: string): any[] => {
-    return [];
-    /*
+  getIntegrations = (categoryType: string) => {
     let { currentProject } = this.context;
     switch (categoryType) {
       case 'kubernetes':
-        api.getProjectClusterIntegrations('<token>', {}, { id: currentProject.id }, (err: any, res: any) => {
+        api.getProjectClusters('<token>', {}, { id: currentProject.id }, (err: any, res: any) => {
           if (err) {
             console.log(err);
           } else {
             console.log(res.data)
-            return [
-              {
-                value: 'gke',
-                label: 'Google Kubernetes Engine (GKE)',
-              },
-              {
-                value: 'eks',
-                label: 'Amazon Elastic Kubernetes Service (EKS)',
-              },
-            ];
           }
         });
+        break;
       case 'registry':
-        return [
-          {
-            value: 'gcr',
-            label: 'Google Container Registry (GCR)',
-          },
-          {
-            value: 'ecr',
-            label: 'Elastic Container Registry (ECR)',
-          },
-          {
-            value: 'docker',
-            label: 'Docker Hub',
-          },
-        ];
+        api.getProjectRegistries('<token>', {}, { id: currentProject.id }, (err: any, res: any) => {
+          if (err) {
+            console.log(err);
+          } else {
+            let currentOptions = [] as string[];
+            res.data.forEach((integration: any, i: number) => {
+              currentOptions.includes(integration.service) ? null : currentOptions.push(integration.service);
+            });
+            this.setState({ currentOptions, currentIntegrationData: res.data });
+          }
+        });
+        break;
+      case 'repo':
+        api.getProjectRepos('<token>', {}, { id: currentProject.id }, (err: any, res: any) => {
+          if (err) {
+            console.log(err);
+          } else {
+            console.log(res.data);
+          }
+        });
+        break;
       default:
-        return [];
+        console.log('Unknown integration category.');
     }
-    */
   }
 
   componentDidUpdate(prevProps: PropsType, prevState: StateType) {
     if (this.state.currentCategory && this.state.currentCategory !== prevState.currentCategory) {
-      this.setState({ currentOptions: this.getIntegrations(this.state.currentCategory.value) });
+      this.getIntegrations(this.state.currentCategory);
+    }
+  }
+
+  renderIntegrationContents = () => {
+    if (this.state.currentIntegrationData) {
+      let items = this.state.currentIntegrationData.filter(item => item.service === this.state.currentIntegration);
+      if (items.length > 0) {
+        return (
+          <div>
+            <Label>Existing Credentials</Label>
+            {
+              items.map((item: any, i: number) => {
+                return (
+                  <Credential>
+                    <i className="material-icons">admin_panel_settings</i> {item.name}
+                  </Credential>
+                );
+              })
+            }
+            <br />
+          </div>
+        );
+      }
     }
   }
 
   renderContents = () => {
     let { currentCategory, currentIntegration } = this.state;
 
+    // TODO: Split integration page into separate component
     if (currentIntegration) {
       let icon = integrationList[currentIntegration] && integrationList[currentIntegration].icon;
       return (
@@ -110,13 +113,21 @@ export default class Integrations extends Component<PropsType, StateType> {
               <Title>{integrationList[currentIntegration].label}</Title>
             </Flex>
           </TitleSectionAlt>
-
-          <IntegrationForm integrationName={currentIntegration} />
+          {this.renderIntegrationContents()}
+          <IntegrationForm 
+            integrationName={currentIntegration}
+            closeForm={() => {
+              this.setState({ currentIntegration: null });
+              this.getIntegrations(this.state.currentCategory);
+            }}
+          />
           <Br />
         </div>
       );
     } else if (currentCategory) {
-      let icon = integrationList[currentCategory.value] && integrationList[currentCategory.value].icon;
+      let icon = integrationList[currentCategory] && integrationList[currentCategory].icon;
+      let label = integrationList[currentCategory] && integrationList[currentCategory].label;
+      let buttonText = integrationList[currentCategory] && integrationList[currentCategory].buttonText;
       return (
         <div>
           <TitleSectionAlt>
@@ -125,23 +136,23 @@ export default class Integrations extends Component<PropsType, StateType> {
                 keyboard_backspace
               </i>
               <Icon src={icon && icon} />
-              <Title>{currentCategory.label}</Title>
+              <Title>{label}</Title>
             </Flex>
 
             <Button 
               onClick={() => this.context.setCurrentModal('IntegrationsModal', { 
-                category: this.state.currentCategory.value,
-                setCurrentIntegration: (x: any) => this.setState({ currentIntegration: x })
+                category: currentCategory,
+                setCurrentIntegration: (x: string) => this.setState({ currentIntegration: x })
               })}
             >
               <i className="material-icons">add</i>
-              {currentCategory.buttonText}
+              {buttonText}
             </Button>
           </TitleSectionAlt>
 
           <IntegrationList
             integrations={this.state.currentOptions}
-            setCurrent={(x: any) => this.setState({ currentIntegration: x })}
+            setCurrent={(x: string) => this.setState({ currentIntegration: x })}
           />
         </div>
       );
@@ -153,7 +164,7 @@ export default class Integrations extends Component<PropsType, StateType> {
         </TitleSection>
 
         <IntegrationList
-          integrations={categories}
+          integrations={['kubernetes', 'registry', 'repo']}
           setCurrent={(x: any) => this.setState({ currentCategory: x })}
           isCategory={true}
         />
@@ -172,6 +183,32 @@ export default class Integrations extends Component<PropsType, StateType> {
 
 Integrations.contextType = Context;
 
+const Label = styled.div`
+  font-size: 14px;
+  font-weight: 500;
+  margin-bottom: 20px;
+`;
+
+const Credential = styled.div`
+  width: 100%;
+  height: 30px;
+  font-size: 13px;
+  display: flex;
+  align-items: center;
+  padding: 20px;
+  padding-left: 13px;
+  width: 100%;
+  border-radius: 5px;
+  background: #ffffff11;
+  margin-bottom: 5px;
+  
+  > i {
+    font-size: 22px;
+    color: #ffffff44;
+    margin-right: 10px;
+  }
+`;
+
 const Br = styled.div`
   width: 100%;
   height: 150px;

+ 1 - 0
dashboard/src/main/home/integrations/integration-form/DockerHubForm.tsx

@@ -8,6 +8,7 @@ import InputRow from '../../../../components/values-form/InputRow';
 import SaveButton from '../../../../components/SaveButton';
 
 type PropsType = {
+  closeForm: () => void,
 };
 
 type StateType = {

+ 35 - 1
dashboard/src/main/home/integrations/integration-form/ECRForm.tsx

@@ -11,10 +11,12 @@ import Heading from '../../../../components/values-form/Heading';
 import Helper from '../../../../components/values-form/Helper';
 
 type PropsType = {
+  closeForm: () => void,
 };
 
 type StateType = {
   credentialsName: string,
+  awsRegion: string,
   awsAccessId: string,
   awsSecretKey: string,
 };
@@ -22,12 +24,34 @@ type StateType = {
 export default class ECRForm extends Component<PropsType, StateType> {
   state = {
     credentialsName: '',
+    awsRegion: '',
     awsAccessId: '',
     awsSecretKey: '',
   }
 
   handleSubmit = () => {
-    // TODO: implement once api is restructured
+    let { awsRegion, awsAccessId, awsSecretKey, credentialsName } = this.state;
+    let { currentProject } = this.context;
+    api.createAWSIntegration('<token>', {
+      aws_region: awsRegion,
+      aws_access_key_id: awsAccessId,
+      aws_secret_access_key: awsSecretKey,
+    }, { id: currentProject.id }, (err: any, res: any) => {
+      if (err) {
+        console.log(err);
+      } else {
+        api.createECR('<token>', {
+          name: credentialsName,
+          aws_integration_id: res.data.id,
+        }, { id: currentProject.id }, (err: any, res: any) => {
+          if (err) {
+            console.log(err);
+          } else {
+            this.props.closeForm();
+          }
+        });
+      }
+    });
   }
 
   render() {
@@ -46,6 +70,14 @@ export default class ECRForm extends Component<PropsType, StateType> {
           />
           <Heading>AWS Settings</Heading>
           <Helper>AWS access credentials.</Helper>
+          <InputRow
+            type='text'
+            value={this.state.awsRegion}
+            setValue={(x: string) => this.setState({ awsRegion: x })}
+            label='📍 AWS Region'
+            placeholder='ex: mars-north-12'
+            width='100%'
+          />
           <InputRow
             type='text'
             value={this.state.awsAccessId}
@@ -73,6 +105,8 @@ export default class ECRForm extends Component<PropsType, StateType> {
   }
 }
 
+ECRForm.contextType = Context;
+
 const CredentialWrapper = styled.div`
   padding: 5px 40px 25px;
   background: #ffffff11;

+ 1 - 0
dashboard/src/main/home/integrations/integration-form/EKSForm.tsx

@@ -11,6 +11,7 @@ import Heading from '../../../../components/values-form/Heading';
 import Helper from '../../../../components/values-form/Helper';
 
 type PropsType = {
+  closeForm: () => void,
 };
 
 type StateType = {

+ 1 - 0
dashboard/src/main/home/integrations/integration-form/GCRForm.tsx

@@ -11,6 +11,7 @@ import Heading from '../../../../components/values-form/Heading';
 import Helper from '../../../../components/values-form/Helper';
 
 type PropsType = {
+  closeForm: () => void,
 };
 
 type StateType = {

+ 1 - 0
dashboard/src/main/home/integrations/integration-form/GKEForm.tsx

@@ -11,6 +11,7 @@ import Heading from '../../../../components/values-form/Heading';
 import Helper from '../../../../components/values-form/Helper';
 
 type PropsType = {
+  closeForm: () => void,
 };
 
 type StateType = {

+ 8 - 6
dashboard/src/main/home/integrations/integration-form/IntegrationForm.tsx

@@ -8,7 +8,8 @@ import GCRForm from './GCRForm';
 import ECRForm from './ECRForm';
 
 type PropsType = {
-  integrationName: string
+  integrationName: string,
+  closeForm: () => void,
 };
 
 type StateType = {
@@ -19,17 +20,18 @@ export default class IntegrationForm extends Component<PropsType, StateType> {
   }
 
   render() {
+    let { closeForm } = this.props;
     switch (this.props.integrationName) {
       case 'docker-hub':
-        return <DockerHubForm />;
+        return <DockerHubForm closeForm={closeForm} />;
       case 'gke':
-        return <GKEForm />;
+        return <GKEForm closeForm={closeForm} />;
       case 'eks':
-        return <EKSForm />;
+        return <EKSForm closeForm={closeForm} />;
       case 'ecr':
-        return <ECRForm />;
+        return <ECRForm closeForm={closeForm} />;
       case 'gcr':
-        return <GCRForm />;
+        return <GCRForm closeForm={closeForm} />;
       default:
         return null;
     }

+ 2 - 2
dashboard/src/main/home/modals/IntegrationsModal.tsx

@@ -33,7 +33,7 @@ export default class IntegrationsModal extends Component<PropsType, StateType> {
         if (err) {
           console.log(err);
         } else {
-          console.log(res.data)
+          // console.log(res.data)
           this.setState({ integrations: res.data });
         }
       });
@@ -53,7 +53,7 @@ export default class IntegrationsModal extends Component<PropsType, StateType> {
       let { setCurrentIntegration } = this.context.currentModalData;
       return this.state.integrations.map((integration: any, i: number) => {
         let icon = integrationList[integration.service] && integrationList[integration.service].icon;
-        let disabled = integration.service === 'kube' || integration.service === 'docker';
+        let disabled = integration.service === 'kube' || integration.service === 'docker' || integration.service === 'gcr';
         return (
           <IntegrationOption 
             key={i}

+ 26 - 9
dashboard/src/shared/api.tsx

@@ -169,16 +169,31 @@ const getRegistryIntegrations = baseApi('GET', '/api/integrations/registry');
 
 const getRepoIntegrations = baseApi('GET', '/api/integrations/repo');
 
-const getProjectClusterIntegrations = baseApi<{}, { id: number }>('GET', pathParams => {
-  return `/api/projects/${pathParams.id}/integrations/cluster`;
+const getProjectClusters = baseApi<{}, { id: number }>('GET', pathParams => {
+  return `/api/projects/${pathParams.id}/clusters`;
+});
+
+const getProjectRegistries = baseApi<{}, { id: number }>('GET', pathParams => {
+  return `/api/projects/${pathParams.id}/registries`;
 });
 
-const getProjectRegistryIntegrations = baseApi<{}, { id: number }>('GET', pathParams => {
-  return `/api/projects/${pathParams.id}/integrations/registry`;
+const getProjectRepos = baseApi<{}, { id: number }>('GET', pathParams => {
+  return `/api/projects/${pathParams.id}/repos`;
 });
 
-const getProjectRepoIntegrations = baseApi<{}, { id: number }>('GET', pathParams => {
-  return `/api/projects/${pathParams.id}/integrations/repo`;
+const createAWSIntegration = baseApi<{
+  aws_region: string,
+  aws_access_key_id: string,
+  aws_secret_access_key: string,
+}, { id: number }>('POST', pathParams => {
+  return `/api/projects/${pathParams.id}/integrations/aws`;
+});
+
+const createECR = baseApi<{
+  name: string,
+  aws_integration_id: string,
+}, { id: number }>('POST', pathParams => {
+  return `/api/projects/${pathParams.id}/registries`;
 });
 
 // Bundle export to allow default api import (api.<method> is more readable)
@@ -210,7 +225,9 @@ export default {
   getClusterIntegrations,
   getRegistryIntegrations,
   getRepoIntegrations,
-  getProjectClusterIntegrations,
-  getProjectRegistryIntegrations,
-  getProjectRepoIntegrations,
+  getProjectClusters,
+  getProjectRegistries,
+  getProjectRepos,
+  createAWSIntegration,
+  createECR,
 }

+ 15 - 9
dashboard/src/shared/common.tsx

@@ -1,4 +1,19 @@
 export const integrationList: any = {
+  'kubernetes': {
+    icon: 'https://uxwing.com/wp-content/themes/uxwing/download/10-brands-and-social-media/kubernetes.png',
+    label: 'Kubernetes',
+    buttonText: 'Add a Cluster',
+  },
+  'repo': {
+    icon: 'https://3.bp.blogspot.com/-xhNpNJJyQhk/XIe4GY78RQI/AAAAAAAAItc/ouueFUj2Hqo5dntmnKqEaBJR4KQ4Q2K3ACK4BGAYYCw/s1600/logo%2Bgit%2Bicon.png',
+    label: 'Git Repository',
+    buttonText: 'Add a Repository',
+  },
+  'registry': {
+    icon: 'https://cdn4.iconfinder.com/data/icons/logos-and-brands/512/97_Docker_logo_logos-512.png',
+    label: 'Docker Registry',
+    buttonText: 'Add a Registry',
+  },
   'gke': {
     icon: 'https://sysdig.com/wp-content/uploads/2016/08/GKE_color.png',
     label: 'Google Kubernetes Engine (GKE)',
@@ -23,15 +38,6 @@ export const integrationList: any = {
     icon: 'https://avatars2.githubusercontent.com/u/52505464?s=400&u=da920f994c67665c7ad6c606a5286557d4f8555f&v=4',
     label: 'Elastic Container Registry (ECR)',
   },
-  'kubernetes': {
-    icon: 'https://uxwing.com/wp-content/themes/uxwing/download/10-brands-and-social-media/kubernetes.png',
-  },
-  'repo': {
-    icon: 'https://3.bp.blogspot.com/-xhNpNJJyQhk/XIe4GY78RQI/AAAAAAAAItc/ouueFUj2Hqo5dntmnKqEaBJR4KQ4Q2K3ACK4BGAYYCw/s1600/logo%2Bgit%2Bicon.png',
-  },
-  'registry': {
-    icon: 'https://cdn4.iconfinder.com/data/icons/logos-and-brands/512/97_Docker_logo_logos-512.png',
-  },
 };
 
 export const getIgnoreCase = (object: any, key: string) => {