Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update destination add to use api endpoint #3058

Merged
merged 3 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func defaultServerOptions(infraDir string) server.Options {
SessionDuration: 24 * time.Hour * 30, // 30 days
SessionExtensionDeadline: 24 * time.Hour * 3, // 3 days
EnableSignup: false,
BaseDomain: "example.com",
BaseDomain: "",

Addr: server.ListenerOptions{
HTTP: ":80",
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ users:
expected.SessionDuration = 3 * time.Minute
expected.SessionExtensionDeadline = 1 * time.Minute
expected.EnableSignup = false
expected.BaseDomain = ""
return expected
},
},
Expand Down
1 change: 1 addition & 0 deletions internal/server/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ func TestAuthenticateRequest(t *testing.T) {
func TestValidateRequestOrganization(t *testing.T) {
srv := setupServer(t, withAdminUser)
srv.options.EnableSignup = true // multi-tenant environment
srv.options.BaseDomain = "example.com"
routes := srv.GenerateRoutes()

org := &models.Organization{
Expand Down
4 changes: 4 additions & 0 deletions internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ func newServer(options Options) *Server {

// New creates a Server, and initializes it. The returned Server is ready to run.
func New(options Options) (*Server, error) {
if options.EnableSignup && options.BaseDomain == "" {
return nil, errors.New("cannot enable signup without setting base domain")
}

server := newServer(options)

if err := importSecrets(options.Secrets, server.secrets); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions internal/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ func TestServer_Run_UIProxy(t *testing.T) {
DBEncryptionKey: filepath.Join(dir, "sqlite3.db.key"),
TLSCache: filepath.Join(dir, "tlscache"),
EnableSignup: true,
BaseDomain: "example.com",
TLS: TLSOptions{
CA: types.StringOrFile(golden.Get(t, "pki/ca.crt")),
CAPrivateKey: string(golden.Get(t, "pki/ca.key")),
Expand Down Expand Up @@ -321,6 +322,7 @@ func TestServer_GenerateRoutes_NoRoute(t *testing.T) {
func TestServer_PersistSignupUser(t *testing.T) {
s := setupServer(t, func(_ *testing.T, opts *Options) {
opts.EnableSignup = true
opts.BaseDomain = "example.com"
opts.SessionDuration = time.Minute
opts.SessionExtensionDeadline = time.Minute
})
Expand Down
9 changes: 3 additions & 6 deletions ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@heroicons/react": "^1.0.6",
"copy-to-clipboard": "^3.3.2",
"dayjs": "^1.11.5",
"js-yaml": "^4.1.0",
"next": "^12.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
89 changes: 74 additions & 15 deletions ui/pages/destinations/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,34 @@ import Head from 'next/head'
import Link from 'next/link'
import { useState, useEffect } from 'react'
import copy from 'copy-to-clipboard'
import yaml from 'js-yaml'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON is valid yaml, so we could potentially avoid this dependency by using JSON.stringify() and writing it out as JSON.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do that but IMO JSON is less user friendly with its quotes and braces and brackets. I don't think it's worth using JSON solely to avoid this dependency.


import Fullscreen from '../../components/layouts/fullscreen'
import { useServerConfig } from '../../lib/serverconfig'

function download(values) {
const blob = new Blob([values], { type: 'application/yaml' })
const href = URL.createObjectURL(blob)
const link = document.createElement('a')

link.href = href
link.setAttribute('download', 'values.yaml')
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(href)
}

export default function DestinationsAdd() {
const [name, setName] = useState('')
const [error, setError] = useState('')
const [submitted, setSubmitted] = useState(false)
const [accessKey, setAccessKey] = useState('')
const [connected, setConnected] = useState(false)
const [copied, setCopied] = useState(false)
const [valuesDownloaded, setValuesDownloaded] = useState(false)
const [valuesCopied, setValuesCopied] = useState(false)
const [commandCopied, setCommandCopied] = useState(false)
const { baseDomain } = useServerConfig()

useEffect(() => {
const interval = setInterval(async () => {
Expand Down Expand Up @@ -66,17 +84,23 @@ export default function DestinationsAdd() {
setSubmitted(true)
}

const server = window.location.host
let command = `helm install infra-connector infrahq/infra \\
--set connector.config.accessKey=${accessKey} \\
--set connector.config.server=${server} \\
--set connector.config.name=${name}`
const server = baseDomain ? `api.${baseDomain}` : window.location.host
const values = {
connector: {
config: {
server: server,
name: name,
},
},
}

if (window.location.protocol !== 'https:') {
command += ` \\
--set connector.config.skipTLSVerify=true`
values.connector.config.skipTLSVerify = true
}

const valuesYaml = yaml.dump(values)
const command = `helm upgrade --install infra-connector infrahq/infra --values values.yaml --set connector.config.accessKey=${accessKey}`

return (
<div>
<Head>
Expand All @@ -90,7 +114,7 @@ export default function DestinationsAdd() {
/>
<h1 className='text-2xs capitalize'>Connect infrastructure</h1>
</header>
<form onSubmit={onSubmit} className='mb-10 flex space-x-2 px-4'>
<form onSubmit={onSubmit} className='mb-6 flex space-x-2 px-4'>
<div className='flex-1'>
<label className='text-3xs uppercase text-gray-400'>
Cluster Name
Expand Down Expand Up @@ -124,25 +148,60 @@ export default function DestinationsAdd() {
}`}
>
<h2 className='mb-2 px-4 text-2xs text-gray-100'>
Run this command on your Kubernetes cluster:
Copy or download this starter Helm values file. For more information
and configuration values, see the{' '}
<Link href='https://github.com/infrahq/infra/tree/main/helm/charts/infra'>
Helm chart
</Link>
.
</h2>
<pre
className={`min-h-[120px] bg-gray-900 p-4 text-2xs text-gray-300 ${
className={`bg-gray-900 p-4 text-2xs text-gray-300 ${
submitted ? 'overflow-auto' : 'overflow-hidden'
}`}
>
{submitted ? valuesYaml : ''}
</pre>
<span className='self-end'>
<button
className='mt-2 mb-3 py-2 px-3 text-3xs font-medium uppercase text-violet-200 disabled:text-gray-500'
disabled={valuesDownloaded}
onClick={() => {
download(valuesYaml)
setValuesDownloaded(true)
setTimeout(() => setValuesDownloaded(false), 3000)
}}
>
{valuesDownloaded ? '✓ Downloaded' : 'Download'}
</button>
<button
className='mt-2 mb-3 mr-2 py-2 px-3 text-3xs font-medium uppercase text-violet-200 disabled:text-gray-500'
disabled={valuesCopied}
onClick={() => {
copy(valuesYaml)
setValuesCopied(true)
setTimeout(() => setValuesCopied(false), 3000)
}}
>
{valuesCopied ? '✓ Copied' : 'Copy'}
</button>
</span>
<h2 className='mb-2 px-4 text-2xs text-gray-100'>
Run this command on your Kubernetes cluster:
</h2>
<pre className={`overflow-auto bg-gray-900 p-4 text-2xs text-gray-300`}>
{submitted ? command : ''}
</pre>
<button
className='mt-2 mb-3 mr-2 self-end py-2 px-3 text-3xs font-medium uppercase text-violet-200 disabled:text-gray-500'
disabled={copied}
disabled={commandCopied}
onClick={() => {
copy(command)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
setCommandCopied(true)
setTimeout(() => setCommandCopied(false), 3000)
}}
>
{copied ? '✓ Copied' : 'Copy command'}
{commandCopied ? '✓ Copied' : 'Copy'}
</button>
<p className='px-4 text-2xs text-gray-500'>
Your cluster will be detected automatically.
Expand Down