Przeglądaj źródła

delete contract

Justin Rhee 3 lat temu
rodzic
commit
294c479d95

+ 6 - 0
api/server/handlers/api_contract/delete.go

@@ -33,6 +33,12 @@ func (c *APIContractRevisionDeleteHandler) ServeHTTP(w http.ResponseWriter, r *h
 
 	ctx := r.Context()
 
+	if revision == nil {
+		e := fmt.Errorf("nil revision")
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(e))
+		return
+	}
+
 	err := c.Config().Repo.APIContractRevisioner().Delete(ctx, proj.ID, 0, revision.ID)
 	if err != nil {
 		e := fmt.Errorf("error delete api contract revision: %w", err)

+ 21 - 5
api/server/handlers/api_contract/update.go

@@ -1,6 +1,7 @@
 package api_contract
 
 import (
+	"encoding/base64"
 	"fmt"
 	"net/http"
 
@@ -46,13 +47,28 @@ func (c *APIContractUpdateHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 	if c.Config().DisableCAPIProvisioner {
 		// return dummy data if capi provisioner disabled
 		// remove this stub when we can spin up all services locally, easily
-		rev := models.APIContractRevision{
-			ID:        uuid.New(),
-			ClusterID: int(apiContract.Cluster.ClusterId),
-			ProjectID: int(apiContract.Cluster.ProjectId),
+		by, err := helpers.MarshalContractObject(ctx, &apiContract)
+		if err != nil {
+			e := fmt.Errorf("error marshalling mock api contract: %w", err)
+			c.HandleAPIError(w, r, apierrors.NewErrInternal(e))
+			return
+		}
+		b64Contract := base64.StdEncoding.EncodeToString([]byte(by))
+
+		revisionInput := models.APIContractRevision{
+			ID:             uuid.New(),
+			ClusterID:      int(apiContract.Cluster.ClusterId),
+			ProjectID:      int(apiContract.Cluster.ProjectId),
+			Base64Contract: b64Contract,
+		}
+		revision, err := c.Config().Repo.APIContractRevisioner().Insert(ctx, revisionInput)
+		if err != nil {
+			e := fmt.Errorf("error updating mock contract: %w", err)
+			c.HandleAPIError(w, r, apierrors.NewErrInternal(e))
+			return
 		}
 		w.WriteHeader(http.StatusCreated)
-		c.WriteResult(w, r, rev)
+		c.WriteResult(w, r, revision)
 		return
 	}
 

BIN
dashboard/src/assets/pencil.png


+ 1 - 0
dashboard/src/components/ExpandableSection.tsx

@@ -49,6 +49,7 @@ const HeaderRow = styled.div<{
   height: 40px;
   font-size: 13px;
   width: 100%;
+  margin-top: -1px;
   padding-left: 10px;
   cursor: pointer;
   :hover {

+ 90 - 7
dashboard/src/main/home/cluster-dashboard/dashboard/ClusterRevisionSelector.tsx

@@ -3,6 +3,7 @@ import styled from "styled-components";
 
 import api from "shared/api";
 import loading from "assets/loading.gif";
+import pencil from "assets/pencil.png";
 
 import { readableDate } from "shared/string_utils";
 import { Context } from "shared/Context";
@@ -31,16 +32,24 @@ const ClusterRevisionSelector: React.FC<Props> = ({
   const [versions, setVersions] = useState<any[]>(null);
   const [selectedId, setSelectedId] = useState(null);
   const [pendingContract, setPendingContract] = useState(null);
+  const [failedContractId, setFailedContractId] = useState("");
 
   const processVersions = (data: any) => {
+    setFailedContractId("");
     data.sort((a: any, b: any) => {
       return Date.parse(a.CreatedAt) > Date.parse(b.CreatedAt) ? -1 : 1;
     });
     let activeCandidate;
-    if (data[0].condition === "") {
+    if (data[0].condition !== "SUCCESS") {
       activeCandidate = data[0];
       setPendingContract(activeCandidate);
-    };
+
+      if (data[0].condition !== "") {
+        console.log(data[0])
+        setFailedContractId(data[0].id);
+      }
+    }
+
     const successes = data.filter((x: any) => {
       return x.condition === "SUCCESS";
     });
@@ -58,7 +67,7 @@ const ClusterRevisionSelector: React.FC<Props> = ({
     setVersions(successes);
   }
 
-  useEffect(() => {
+  const updateContracts = () => {
     api.getContracts(
       "<token>",
       {},
@@ -73,6 +82,10 @@ const ClusterRevisionSelector: React.FC<Props> = ({
       .catch((err) => {
         console.error(err);
       });
+  };
+
+  useEffect(() => {
+    updateContracts();
   }, [currentCluster]);
   
   const createContract = () => {
@@ -90,6 +103,23 @@ const ClusterRevisionSelector: React.FC<Props> = ({
     }
   };
 
+const deleteContract = () => {
+    api.deleteContract(
+      "<token>",
+      {},
+      { 
+        project_id: currentProject.id,
+        revision_id: failedContractId,
+      }
+    )
+      .then(() => {
+        updateContracts();
+      })
+      .catch((err) => {
+        console.log(err);
+      });
+  };
+
   const renderVersionList = () => {
     return versions?.map((version: any, i: number) => {
       return (
@@ -129,7 +159,15 @@ const ClusterRevisionSelector: React.FC<Props> = ({
         }}
         selected={selectedId === -1}
       >
-        <Td><Flex><Img src={loading} /> Updating</Flex></Td>
+        <Td>
+          {
+            failedContractId ? (
+              <Failed>Failed</Failed>
+            ) : (
+              <Flex><Img src={loading} /> Updating</Flex>
+            )
+          }
+        </Td>
         <Td>{readableDate(pendingContract.CreatedAt)}</Td>
         {/*
         <Td>
@@ -158,7 +196,11 @@ const ClusterRevisionSelector: React.FC<Props> = ({
                   "Current version -"
                 ) : (
                   selectedId === -1 ? (
-                    "In progress -"
+                    failedContractId ? (
+                      "Update failed -"
+                    ) : (
+                      "In progress -"
+                    )
                   ) : (
                     "Previewing revision (not deployed) -"
                   )
@@ -167,7 +209,19 @@ const ClusterRevisionSelector: React.FC<Props> = ({
             </Label>
             {
               selectedId === -1 ? (
-                <><Img src={loading} /> Updating</>
+                failedContractId ? (
+                  <>
+                    <Button onClick={(e) => {
+                      deleteContract();
+                      e.stopPropagation();
+                    }}>
+                      <Icon src={pencil} />
+                      Clear attempt
+                    </Button>
+                  </>
+                ) : (
+                  <><Img src={loading} /> Updating</>
+                )
               ) : (
                 `No. ${versions?.length - selectedId}`
               )
@@ -183,7 +237,7 @@ const ClusterRevisionSelector: React.FC<Props> = ({
                   <Th>Created</Th>
                   {/* <Th>Rollback</Th> */}
                 </Tr>
-                {pendingContract && renderActiveAttempt()}
+                {(pendingContract || failedContractId) && renderActiveAttempt()}
                 {renderVersionList()}
               </tbody>
             </RevisionsTable>
@@ -196,6 +250,35 @@ const ClusterRevisionSelector: React.FC<Props> = ({
 
 export default ClusterRevisionSelector;
 
+const Icon = styled.img`
+  height: 15px;
+  margin-right: 5px;
+  margin-left: -2px;
+`;
+
+const Button = styled.div`
+  border-radius: 3px;
+  padding: 10px;
+  height: 26px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #616FEEcc;
+  :hover {
+    background: #505edddd;
+  }
+`;
+
+const Failed = styled.div`
+  background: #cc3d42;
+  width: 55px;
+  border-radius: 3px;
+  height: 22px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+`;
+
 const Flex = styled.div`
   display: flex;
   align-items: center;

+ 5 - 3
dashboard/src/main/home/cluster-dashboard/dashboard/ProvisionerStatus.tsx

@@ -1,6 +1,7 @@
 import React, { useEffect, useState, useContext } from "react";
 import styled from "styled-components";
 
+import aws from "assets/aws.png";
 import api from "shared/api";
 import loading from "assets/loading.gif";
 
@@ -19,8 +20,8 @@ const ProvisionerStatus: React.FC<Props> = ({}) => {
         isInitiallyExpanded={true}
         Header={(
           <>
-            <Icon src="https://img.stackshare.io/service/7991/amazon-eks.png" />
-            Elastic Kubernetes Service
+            <Icon src={aws} />
+            AWS provisioning status
           </>
         )}
         ExpandedSection={(
@@ -45,8 +46,9 @@ const DummyLogs = styled.div`
 `;
 
 const Icon = styled.img`
-  height: 20px;
+  height: 16px;
   margin-right: 10px;
+  margin-bottom: -1px;
 `;
 
 const Img = styled.img`

+ 8 - 0
dashboard/src/shared/api.tsx

@@ -903,6 +903,13 @@ const getContracts = baseApi<
   return `/api/projects/${project_id}/contracts`;
 });
 
+const deleteContract = baseApi<
+  {},
+  { project_id: number, revision_id: string }
+>("DELETE", ({ project_id, revision_id }) => {
+  return `/api/projects/${project_id}/contracts/${revision_id}`;
+});
+
 const provisionInfra = baseApi<
   {
     kind: string;
@@ -2558,6 +2565,7 @@ export default {
   getIncidentEvents,
   createContract,
   getContracts,
+  deleteContract,
   // STACKS
   listStacks,
   getStack,