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

Merge branch 'capi-preflight-checks' of github.com:porter-dev/porter into capi-preflight-checks

Feroze Mohideen 3 лет назад
Родитель
Сommit
92fbf1a05c

+ 6 - 2
Tiltfile

@@ -12,10 +12,14 @@ if config.tilt_subcommand == "down":
     local(command="rm -rf vendor")
     local(command="rm -rf dashboard/node_modules")
 
+build_args = "GOOS=linux GOARCH=arm64"
+if os.getenv("PLATFORM") == "amd64":
+    build_args = "GOOS=linux GOARCH=amd64"
+
 ## Build binary locally for faster devexp
 local_resource(
   name='porter-binary',
-  cmd='''GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -mod vendor -gcflags '-N -l' -tags ee -o ./bin/porter ./cmd/app/main.go''',
+  cmd='''GOWORK=off CGO_ENABLED=0 %s go build -mod vendor -gcflags '-N -l' -tags ee -o ./bin/porter ./cmd/app/main.go''' % build_args,
   deps=[
     "api",
     "build",
@@ -62,7 +66,7 @@ local_resource(
 # Migrations
 local_resource(
     name="migrations-binary",
-    cmd='''GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -mod vendor -gcflags '-N -l' -tags ee -o ./bin/migrate ./cmd/migrate/main.go ./cmd/migrate/migrate_ee.go''',
+    cmd='''GOWORK=off CGO_ENABLED=0 %s go build -mod vendor -gcflags '-N -l' -tags ee -o ./bin/migrate ./cmd/migrate/main.go ./cmd/migrate/migrate_ee.go''' % build_args,
     resource_deps=["postgresql"],
     labels=["porter"],
 )

+ 36 - 16
api/server/handlers/user/create_test.go

@@ -1,7 +1,6 @@
 package user_test
 
 import (
-	"fmt"
 	"net/http"
 	"testing"
 
@@ -18,8 +17,11 @@ func TestCreateUserSuccessful(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/users",
 		&types.CreateUserRequest{
-			Email:    "test@test.it",
-			Password: "somepassword",
+			FirstName:   "Mister",
+			LastName:    "Porter",
+			CompanyName: "Porter Technologies, Inc.",
+			Email:       "mrp@porter.run",
+			Password:    "somepassword",
 		},
 	)
 
@@ -35,7 +37,10 @@ func TestCreateUserSuccessful(t *testing.T) {
 
 	expUser := &types.CreateUserResponse{
 		ID:            1,
-		Email:         "test@test.it",
+		FirstName:     "Mister",
+		LastName:      "Porter",
+		CompanyName:   "Porter Technologies, Inc.",
+		Email:         "mrp@porter.run",
 		EmailVerified: false,
 	}
 
@@ -50,8 +55,11 @@ func TestCreateUserBadEmail(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/users",
 		&types.CreateUserRequest{
-			Email:    "notanemail",
-			Password: "somepassword",
+			FirstName:   "Mister",
+			LastName:    "Porter",
+			CompanyName: "Porter Technologies, Inc.",
+			Email:       "notanemail",
+			Password:    "somepassword",
 		},
 	)
 
@@ -66,7 +74,7 @@ func TestCreateUserBadEmail(t *testing.T) {
 	handler.ServeHTTP(rr, req)
 
 	apitest.AssertResponseError(t, rr, http.StatusBadRequest, &types.ExternalError{
-		Error: fmt.Sprintf("validation failed on field 'Email' on condition 'email'"),
+		Error: "validation failed on field 'Email' on condition 'email'",
 	})
 }
 
@@ -76,7 +84,10 @@ func TestCreateUserMissingField(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/users",
 		&types.CreateUserRequest{
-			Email: "test@test.it",
+			FirstName:   "Mister",
+			LastName:    "Porter",
+			CompanyName: "Porter Technologies, Inc.",
+			Email:       "mrp@porter.run",
 		},
 	)
 
@@ -91,7 +102,7 @@ func TestCreateUserMissingField(t *testing.T) {
 	handler.ServeHTTP(rr, req)
 
 	apitest.AssertResponseError(t, rr, http.StatusBadRequest, &types.ExternalError{
-		Error: fmt.Sprintf("validation failed on field 'Password' on condition 'required'"),
+		Error: "validation failed on field 'Password' on condition 'required'",
 	})
 }
 
@@ -101,8 +112,11 @@ func TestCreateUserSameEmail(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/users",
 		&types.CreateUserRequest{
-			Email:    "test@test.it",
-			Password: "somepassword",
+			FirstName:   "Mister",
+			LastName:    "Porter",
+			CompanyName: "Porter Technologies, Inc.",
+			Email:       "mrp@porter.run",
+			Password:    "somepassword",
 		},
 	)
 
@@ -120,7 +134,7 @@ func TestCreateUserSameEmail(t *testing.T) {
 	handler.ServeHTTP(rr, req)
 
 	apitest.AssertResponseError(t, rr, http.StatusBadRequest, &types.ExternalError{
-		Error: fmt.Sprintf("email already taken"),
+		Error: "email already taken",
 	})
 }
 
@@ -130,8 +144,11 @@ func TestFailingCreateUserMethod(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/users",
 		&types.CreateUserRequest{
-			Email:    "test@test.it",
-			Password: "somepassword",
+			FirstName:   "Mister",
+			LastName:    "Porter",
+			CompanyName: "Porter Technologies, Inc.",
+			Email:       "mrp@porter.run",
+			Password:    "somepassword",
 		},
 	)
 
@@ -154,8 +171,11 @@ func TestFailingCreateSessionMethod(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/users",
 		&types.CreateUserRequest{
-			Email:    "test@test.it",
-			Password: "somepassword",
+			FirstName:   "Mister",
+			LastName:    "Porter",
+			CompanyName: "Porter Technologies, Inc.",
+			Email:       "mrp@porter.run",
+			Password:    "somepassword",
 		},
 	)
 

+ 4 - 1
api/server/handlers/user/current_test.go

@@ -25,7 +25,10 @@ func TestGetCurrentUserSuccessful(t *testing.T) {
 
 	expUser := &types.GetAuthenticatedUserResponse{
 		ID:            1,
-		Email:         "test@test.it",
+		FirstName:     "Mister",
+		LastName:      "Porter",
+		CompanyName:   "Porter Technologies, Inc.",
+		Email:         "mrp@porter.run",
 		EmailVerified: true,
 	}
 

+ 4 - 1
api/server/handlers/user/delete_test.go

@@ -33,7 +33,10 @@ func TestDeleteUserSuccessful(t *testing.T) {
 
 	expUser := &types.CreateUserResponse{
 		ID:            1,
-		Email:         "test@test.it",
+		FirstName:     "Mister",
+		LastName:      "Porter",
+		CompanyName:   "Porter Technologies, Inc.",
+		Email:         "mrp@porter.run",
 		EmailVerified: true,
 	}
 

+ 1 - 1
api/server/handlers/user/email_verify_test.go

@@ -33,7 +33,7 @@ func TestEmailVerifyInitiateSuccessful(t *testing.T) {
 	}
 
 	initiateOpts := fakeNotifier.GetSendEmailVerificationLastOpts()
-	assert.Equal(t, "test@test.it", initiateOpts.Email)
+	assert.Equal(t, "mrp@porter.run", initiateOpts.Email)
 
 	// parse the url and compare
 	parsedURL, err := url.Parse(initiateOpts.URL)

+ 8 - 5
api/server/handlers/user/login_test.go

@@ -18,7 +18,7 @@ func TestLoginUserSuccessful(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/login",
 		&types.LoginUserRequest{
-			Email:    "test@test.it",
+			Email:    "mrp@porter.run",
 			Password: "hello",
 		},
 	)
@@ -36,7 +36,10 @@ func TestLoginUserSuccessful(t *testing.T) {
 
 	expUser := &types.LoginUserResponse{
 		ID:            1,
-		Email:         "test@test.it",
+		FirstName:     "Mister",
+		LastName:      "Porter",
+		CompanyName:   "Porter Technologies, Inc.",
+		Email:         "mrp@porter.run",
 		EmailVerified: true,
 	}
 
@@ -51,7 +54,7 @@ func TestLoginUserIncorrectPassword(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/login",
 		&types.LoginUserRequest{
-			Email:    "test@test.it",
+			Email:    "mrp@porter.run",
 			Password: "hello1",
 		},
 	)
@@ -105,7 +108,7 @@ func TestLoginUserEmptyPassword(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/login",
 		&types.LoginUserRequest{
-			Email:    "test@test.it",
+			Email:    "mrp@porter.run",
 			Password: "",
 		},
 	)
@@ -157,7 +160,7 @@ func TestLoginUserFailingReadUserByEmailMethod(t *testing.T) {
 		string(types.HTTPVerbPost),
 		"/api/login",
 		&types.LoginUserRequest{
-			Email:    "test@test.it",
+			Email:    "mrp@porter.run",
 			Password: "hello",
 		},
 	)

+ 4 - 1
api/server/shared/apitest/user.go

@@ -12,7 +12,10 @@ func CreateTestUser(t *testing.T, config *config.Config, verified bool) *models.
 	hashedPw, _ := bcrypt.GenerateFromPassword([]byte("hello"), 8)
 
 	user, err := config.Repo.User().CreateUser(&models.User{
-		Email:         "test@test.it",
+		FirstName:     "Mister",
+		LastName:      "Porter",
+		CompanyName:   "Porter Technologies, Inc.",
+		Email:         "mrp@porter.run",
 		Password:      string(hashedPw),
 		EmailVerified: verified,
 	})

+ 5 - 2
dashboard/src/components/CloudFormationForm.tsx

@@ -18,7 +18,7 @@ import DocsHelper from "./DocsHelper";
 
 type Props = {
   goBack: () => void;
-  proceed: () => void;
+  proceed: (id: string) => void;
   AWSAccountID: string;
   setAWSAccountID: (id: string) => void;
 };
@@ -55,7 +55,7 @@ const CloudFormationForm: React.FC<Props> = ({
     //     setCreateStatus("Error creating credentials");
     //   });
     setRoleStatus("successful");
-    proceed();
+    proceed(targetARN);
   };
 
   const directToCloudFormation = () => {
@@ -85,6 +85,9 @@ const CloudFormationForm: React.FC<Props> = ({
                 👤 AWS account ID
                 <i
                   className="material-icons"
+                  onClick={() => {
+                    window.open("https://console.aws.amazon.com/billing/home?region=us-east-1#/account", "_blank")
+                  }}
                 >
                   help_outline
                 </i>

+ 16 - 22
dashboard/src/components/ProvisionerFlow.tsx

@@ -72,25 +72,24 @@ const ProvisionerFlow: React.FC<Props> = ({
             setShowCostConfirmModal(false);
           }}>
             <Text size={16} weight={500}>
-              AWS base cost consent
+              Base AWS cost consent
             </Text>
             <Spacer height="15px" />
             <Text color="helper">
-              Porter will create resources in your existing AWS account for hosting your applications. You will be separately charged by AWS and can use your cloud credits.
-            </Text>
-            <Spacer y={1} />
-            <Text color="helper">
-              AWS base cost before cloud credits:
+              Porter will create resources in your existing AWS account for hosting applications. You will be separately charged by AWS and can use your cloud credits. Base AWS cost:
             </Text>
             <Spacer y={1} />
             <ExpandableSection
-              background="#ffffff11"
+              noWrapper
+              expandText="[+] Show details"
+              collapseText="[-] Hide details"
               Header={
                 <Cost>$315.94 / mo</Cost>
               }
               ExpandedSection={
-                <Dark>
-                  <Text>
+                <>
+                  <Spacer height="15px" />
+                  <Fieldset background="#1b1d2688">
                     • Amazon Elastic Kubernetes Service (EKS) = $73/mo
                     <Spacer height="15px" />
                     • Amazon EC2:
@@ -100,17 +99,19 @@ const ProvisionerFlow: React.FC<Props> = ({
                     <Tab />+ Monitoring workloads: t3.large instance (1) = $60.74/mo
                     <Spacer height="15px" />
                     <Tab />+ Application workloads: t3.xlarge instance (1) = $121.47/mo
-                  </Text>
-                </Dark>
+                  </Fieldset>
+                </>
               }
             />
             <Spacer y={1} />
             <Text color="helper">
-              Porter metered cost: $0.019/hr/vCPU + $0.009/hr/GB RAM.
+              Separate from the AWS cost, Porter charges based on the amount of resources that are being used. Porter pricing is as follows, prorated to the minute:
             </Text>
+            <Spacer y={1}/>
+            <Cost>$0.019/hr/vCPU + $0.009/hr/GB RAM</Cost>
             <Spacer y={1} />
             <Text color="helper">
-              All AWS resources will be automatically deleted when you delete your Porter project. Please enter the base cost ("315.94") below to proceed:
+              All AWS resources will be automatically deleted when you delete your Porter project. Please enter the AWS base cost ("315.94") below to proceed:
             </Text>
             <Spacer y={1} />
             <Input placeholder="315.94" value={confirmCost} setValue={setConfirmCost} width="100%" height="40px" />
@@ -133,8 +134,8 @@ const ProvisionerFlow: React.FC<Props> = ({
     return (
       <CloudFormationForm
         goBack={() => setCurrentStep("cloud")}
-        proceed={() => {
-          // setCredentialId(id);
+        proceed={(id) => {
+          setCredentialId(id);
           setCurrentStep("cluster");
         }}
         AWSAccountID={AWSAccountID}
@@ -154,13 +155,6 @@ const ProvisionerFlow: React.FC<Props> = ({
 
 export default ProvisionerFlow;
 
-const Dark = styled.div`
-  position: relative;
-  padding: 25px;
-  background: #1b1d2688;
-  font-size: 13px;
-`;
-
 const Cost = styled.div`
   font-weight: 600;
   font-size: 20px;

+ 41 - 14
dashboard/src/components/porter/ExpandableSection.tsx

@@ -1,5 +1,6 @@
 import React, { useEffect, useState } from "react";
 import styled from "styled-components";
+import Container from "./Container";
 
 type Props = {
   isInitiallyExpanded?: boolean;
@@ -7,6 +8,10 @@ type Props = {
   ExpandedSection: any;
   color?: any;
   background?: string;
+  noWrapper?: boolean;
+  expandText?: string;
+  collapseText?: string;
+  maxHeight?: string;
 };
 
 const ExpandableSection: React.FC<Props> = ({
@@ -15,6 +20,10 @@ const ExpandableSection: React.FC<Props> = ({
   ExpandedSection,
   color,
   background,
+  noWrapper,
+  expandText,
+  collapseText,
+  maxHeight,
 }) => {
   const [isExpanded, setIsExpanded] = useState(false);
   useEffect(() => {
@@ -25,15 +34,25 @@ const ExpandableSection: React.FC<Props> = ({
     <StyledExpandableSection 
       isExpanded={isExpanded}
       background={background}
+      noWrapper={noWrapper}
     >
-      <HeaderRow 
-        isExpanded={isExpanded}
-        onClick={() => setIsExpanded(!isExpanded)}
-        color={color}
-      >
-        <i className="material-icons">arrow_drop_down</i> 
-        {Header}
-      </HeaderRow>
+      {noWrapper ? (
+        <Container row>
+          {Header}
+          <ExpandButton onClick={() => setIsExpanded(!isExpanded)}>
+            {isExpanded ? collapseText : expandText}
+          </ExpandButton>
+        </Container>
+      ) : (
+        <HeaderRow 
+          isExpanded={isExpanded}
+          onClick={() => setIsExpanded(!isExpanded)}
+          color={color}
+        >
+          {!noWrapper && <i className="material-icons">arrow_drop_down</i>}
+          {Header}
+        </HeaderRow>
+      )}
       {
         isExpanded && (
           ExpandedSection
@@ -45,6 +64,13 @@ const ExpandableSection: React.FC<Props> = ({
 
 export default ExpandableSection;
 
+const ExpandButton = styled.div`
+  margin-left: 15px;
+  color: #aaaabb;
+  cursor: pointer;
+  font-size: 13px;
+`;
+
 const HeaderRow = styled.div<{ 
   isExpanded: boolean;
   color?: string;
@@ -74,16 +100,17 @@ const HeaderRow = styled.div<{
 const StyledExpandableSection = styled.div<{ 
   isExpanded: boolean;
   background?: string;
+  noWrapper?: boolean;
 }>`
   width: 100%;
-  height: ${props => props.isExpanded ? "" : "40px"};
-  max-height: 255px;
+  height: ${props => (props.isExpanded || props.noWrapper) ? "" : "40px"};
+  max-height: 300px;
   overflow: hidden;
   border-radius: 5px;
-  background: ${props => props.background || "#26292e"};
-  border: 1px solid #494b4f;
+  background: ${props => !props.noWrapper && (props.background || "#26292e")};
+  border: ${props => !props.noWrapper && "1px solid #494b4f"};
   :hover {
-    border: 1px solid #7a7b80;
+    border: ${props => !props.noWrapper && "1px solid #7a7b80"};
   }
   animation: ${props => props.isExpanded ? "expandRevisions 0.3s" : ""};
   animation-timing-function: ease-out;
@@ -92,7 +119,7 @@ const StyledExpandableSection = styled.div<{
       max-height: 40px;
     }
     to {
-      max-height: 250px;
+      max-height: 300px;
     }
   }
 `;

+ 3 - 1
dashboard/src/components/porter/Spacer.tsx

@@ -3,6 +3,7 @@ import styled from "styled-components";
 
 type Props = {
   height?: string;
+  width?: string;
   y?: number;
   x?: number;
   inline?: boolean;
@@ -10,6 +11,7 @@ type Props = {
 
 const Spacer: React.FC<Props> = ({
   height,
+  width,
   y,
   x,
   inline,
@@ -31,7 +33,7 @@ const Spacer: React.FC<Props> = ({
   return (
     <StyledSpacer
       height={height || getCalcHeight()}
-      width={inline && getCalcWidth()}
+      width={inline && (width || getCalcWidth())}
     />
   );
 };

+ 1 - 1
dashboard/src/main/auth/Login.tsx

@@ -226,7 +226,7 @@ const Login: React.FC<Props> = ({
           size={13}
           color="helper"
         >
-          Don't have an account? <Link to="/register">Sign up</Link>
+          Don't have an account?<Spacer width="5px" inline /><Link to="/register">Sign up</Link>
         </Text>
       </Wrapper>
     </StyledLogin>

+ 1 - 1
dashboard/src/main/auth/Register.tsx

@@ -292,7 +292,7 @@ const Register: React.FC<Props> = ({
           size={13}
           color="helper"
         >
-          Already have an account? <Link to="/login">Log in</Link>
+          Already have an account?<Spacer width="5px" inline /><Link to="/login">Log in</Link>
         </Text>
       </Wrapper>
     </StyledRegister>

+ 1 - 1
dashboard/src/main/auth/VerifyEmail.tsx

@@ -125,7 +125,7 @@ const Register: React.FC<Props> = ({
           size={13}
           color="helper"
         >
-          Want to use a different email? <Link onClick={handleLogOut}>Log out</Link>
+          Want to use a different email?<Spacer inline width="5px" /><Link onClick={handleLogOut}>Log out</Link>
         </Text>
       </Wrapper>
     </StyledRegister>

+ 3 - 2
dashboard/src/main/home/modals/Modal.tsx

@@ -146,8 +146,9 @@ const StyledModal = styled.div<{
   z-index: 999;
   font-size: 13px;
   border-radius: 10px;
-  background: #202227;
-  border: 1px solid #ffffff55;
+  background: #42444944;
+  backdrop-filter: saturate(150%) blur(10px);
+  border: 1px solid #494b4f;
   overflow: auto;
   color: #ffffff;
   animation: floatInModal 0.5s 0s;

+ 5 - 0
go.work.sum

@@ -1,15 +1,20 @@
 cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
 cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
 github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
+github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
 github.com/containerd/stargz-snapshotter v0.11.3 h1:D3PoF563XmOBdtfx2G6AkhbHueqwIVPBFn2mrsWLa3w=
+github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
 github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
 github.com/go-redis/redis v6.15.8+incompatible h1:BKZuG6mCnRj5AOaWJXoCgf6rqTYnYJLe4en2hxT7r9o=
 github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
 github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
+github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f h1:2+myh5ml7lgEU/51gbeLHfKGNfgEQQIWrlbdaOsidbQ=
 github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ=
 github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4=
 github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
 github.com/tchap/go-patricia v2.2.6+incompatible h1:JvoDL7JSoIP2HDE8AbDH3zC8QBPxmzYe32HHy5yQ+Ck=
 golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
 golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=