Skip to content

Commit

Permalink
DN-822 New challenge
Browse files Browse the repository at this point in the history
We need a harder challenge for hiring since the current one does not grasp the full skills that we need.
  • Loading branch information
Marcus Bergo committed Sep 21, 2020
1 parent 8e3c041 commit 635201a
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 107 deletions.
326 changes: 299 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,316 @@
# <img src="https://avatars1.githubusercontent.com/u/7063040?v=4&s=200.jpg" alt="HU" width="24" /> Desafio Delta

Como DevOps voce vai desenhar e implementar arquitetura e sistemas relacionados a build, release, deploy e configurações de aplicações, assim como manter-se atualizado com as tecnologias de mercado.
Serão basicamente 2 partes que vamos focar nesse teste:

Este estudo de caso tem como objetivo testar as habilidades relevantes para esta função. Por favor leia todas as instruções e responda todas as questões.
- Sua habilidade de desenvolvimento.
- Sua habilidade de colocar o código para rodar usando específicas tecnologias.

O projeto consiste em uma API implementada com Node.js​ + MySQL​ para criação e consulta de pacotes.
Você deve:
Alguns passos terão requerimentos vagos ou erros. Não há resposta certa ou errada, queremos avaliar sua postura diante do desafio assim o modo como você o desenvolverá.

- Criar o diagrama de toda a infraestrutura do projeto em questão ( frontend, backend e database );
- Montar toda a infraestrutura utilizando Docker:
- 1 container rodando a aplicação em Node.js;
- 1 container rodando um banco de dados MySQL;
- 1 container rodando um servidor nginx;
- Rodar a aplicação frontend na porta 80 e colocar o nginx ​como reverse proxy. O unico path disponivel deve ser o /packages, todos os demais paths devem ser redirecionados para o path default;
- Preparar o banco de dados para ser usado pela aplicação;
- Fornecer comandos para criação e inicialização do ambiente de forma automatizada
- (**diferencial**) Usar minikube ( utilizando kubectl )
- Fornecer os comandos necessário para criar e deletar os pacotes;
- Todos os logs ( access e error ) devem estar diponiveis via "docker logs".
#
# Parte 1 - Desenvolvimento

## Pre-requisitos
* Git
* Conta no Github
#
### Como fazer

O projeto deve usar controle de versão no git e armazenado/subido para o Github em um repositório privado na sua conta.

Quando terminar o desafio, convide o usuário `automator-hurb` para colaborador do seu repositório do desafio para que possamos fazer a avaliação.
#
## A tarefa

Usando Go, Python3 ou NodeJS, sua tarefa, será implementar um API REST que faça CRUD em produtos armazenados em um banco de dados MySQL 5.7.

A API terá que fazer a validação dos dados de entrada. Exemplo: SKU é único em POST e PUT.
#
## Requisitos
- Kubernetes deployment manifests para rodar, balancear, limitar requests e escalar utilizando HPA no Minikube v13.0

- Script para popular o banco de dados com dummy data.

- Testes unitários

## Bibliotecas de terceiros
Você poderá usar bibliotecas de terceiros, como por exemplo o driver para falar com o banco de dados, mas encorajamos que use o menor número de bibliotecas possíveis.

# API de Produtos
Response codes
- 200 OK
- 201 Created
- 400 Bad Request
- 404 Not Found
- 500 Internal Server Error

---
Todas as respostas de erro (400, 404, 500) devem retornar um objeto único com uma única chave chamada "errorText" e o valor (string) descrevendo o erro.

Exemplo:

```
{
"errorText": "The error message"
}
```
## Definição do "produto"
```
{
"productId"​: ​<int>​, ​(readonly, unique)
"title"​: ​<string>​, ​(required for POST)
​ "sku"​: ​<string>​, ​(required for POST, unique)
"barcodes"​: ​[<string>]​, (unique)
"description"​: <string|null>​, (default null)
"attributes"​: ​[<attribute>]​, ​
"price"​: ​<money>​, ​(default "0.00")
"created"​: <timestamp>​, (readonly)
"lastUpdated": <timestamp|null>​ (readonly)
}
```


## Endpoints
```GET /api/products```

**Parametros de query**

Todos os parametros são opcionais



| Parâmetro | Descrição | Tipo | Default |
|---|---|---|---|
| start | Inicio do index | int | 0 |
| num | Numero de indexes retornados | int | 10 |
| sku | Filtrar por sku | string | --- |
| barcode | Filtrar por barcode | string | |
| fields | Campos do produto que serão retornados da resposta | string, separado por vírgulas | --- |

- Exemplo da URL
```
http://127.0.0.1:8080/api/products?start=40&num=2&fields=productId,title
```

- Retorno sucesso
```
{
"totalCount"​: <int>​,
"items"​: [​<product>​]
}
```
- Exemplo de retorno
```
{
​"totalCount"​: 126​,
"items"​: [
{
"productId"​: 45​,
​ "title": "Awesome socks"
},
{
"productId"​: 46​,
"title"​: "Batman socks"
}
]
}
```
---

## GET
```
GET /api/products/{productId}
```

**Parametros de query**

Todos os parametros são opcionais



| Parâmetro | Descrição | Tipo | Default |
|---|---|---|---|
| fields | Campos do produto que serão retornados da resposta | string, separado por vírgulas | --- |

Exemplo Retorno sucesso
```
{
"productId"​: 45​,
"title"​: "Awesome socks"​,
​"sku"​: "SCK-4511"​,
​"barcodes"​: [​"7410852096307"​],
"description"​: null​,
"attributes"​: [
{
​ "name"​: "color"​,
​ "value"​: "Red"
},
{
"name"​: "size"​,​
"value"​: "39-41"
},
],
"price"​: "89.00",
"created"​: 1554472112​,
​"lastUpdated"​: null
}
```


Retorno erro
```
{
"errorText"​: "Can’t find product (<productId>)"
}
```
---
## POST

```
POST​ /api/products
```

Para POST, um subset de produto é permitido, porém todos os campos requeridos para criação devem estar presentes.

**Body** content
```
{
​"title": "Awesome socks"​,
"sku"​: "SCK-4511"​,
"barcodes"​: [​"7410852096307"​],
​"description"​: null​,
​"attributes"​: [
{
"name"​: "color"​,
"value"​: "Red"​,
},
{
​ "name": "size"​,
"value"​: "39-41"​,
},
],
​"price"​: "89.00"​,
}
```
* Resposta sucesso (int)
```
45
```
* Resposta erro
```
{
​"errorText"​: "SKU 'SCK-4511' already exists"
}
```
---
## PUT

```
PUT​ /api/products/{productId}
```

Novamente, um subset de produto é permitido.

Retorno sucesso (bool)
```
true
```

Retorno erro
```
{
"errorText": "​ Invalid sku, can not be null"
}
```
---
## DELETE
```
DELETE​ /api/products/{productId}
```

Retorno sucesso (bool)
```
true
```
Retorno erro
```
{
​"errorText"​: "Product with productId (<productId>) does not exist"
}
```

# Definições

## Tipos API

Atributos
```
{
"name"​: ​<string>​, ​(required)​
"value"​: ​<string>​ ​(required)
}
```

## Mysql schema
```
CREATE​ SCHEMA ​IF​ ​NOT​ ​EXISTS​ ​`hurb_test_assignment`
DEFAULT ​CHARACTER​ SET​ utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE​ ​TABLE​ ​IF​ ​NOT​ ​EXISTS​ ​`hurb_test_assignment`​.`product`​ (
`product_id`​ INT​ UNSIGNED ​NOT​ NULL​ AUTO_INCREMENT,
`title`​ VARCHAR​(32​) NOT​ NULL​,
`sku`​ VARCHAR​(32​) NOT​ NULL​,
`description`​ VARCHAR(1024​) NULL​,
`price`​ DECIMAL​(12​,2)NOT​ NULL​ DEFAULT ​0.00,
`created`​ DATETIME​ NOT​ NULL​,
`last_updated`​ DATETIME​ NULL,
PRIMARY​ KEY​ (​`product_id`​),
UNIQUE INDEX (​`sku`​ ASC​),
INDEX (​
`created`​
),
INDEX (​`last_updated`​)
);
CREATE​ ​TABLE​ ​IF​ ​NOT​ ​EXISTS​ ​`hurb_test_assignment`​.`product_barcode`​ (
`product_id`​ INT​ UNSIGNED ​NOT​ NULL​,
`barcode`​ VARCHAR(32​) NOT​ NULL​,
PRIMARY​ KEY​ (​`product_id`​, `barcode`​),
UNIQUE INDEX (​`barcode`​)
);
CREATE​ ​TABLE​ ​IF​ ​NOT​ ​EXISTS​ ​`hurb_test_assignment`​.`product_attribute`​ (
`product_id`​ INT​ UNSIGNED ​NOT​ NULL​,
`name`​ VARCHAR​(16​) NOT​ NULL​,
`value`​ VARCHAR​(32​) NOT​ NULL​,
PRIMARY​ KEY​ (​`product_id`​, `name`​)
);
```

#
# Parte 2 - Entrega da aplicação

- Sua aplicação deve rodar no Minikube v13.0 + kubectl
- Você deve escrever os manifestos do Kubernetes para criar o *Ingresso* para expor sua app, 1 container para rodar sua aplicação e 1 container para rodar o Banco de dados. Você deve utilizar Serviços e deployments do K8s assim como HPA setando limites de requests e uso de recursos do sistema. Os números desses limites devem ser baixos o suficiente para ser possivel ver o HPA entrar em ação a partir de requisições da máquina local.

* Todos os logs devem ser visiveis a partir do `kubectl logs -f <pod>`

* A segurança do cluster será levada em consideração.

- Forkar esse desafio e criar o seu projeto (ou workspace) usando a sua versão desse repositório, tão logo acabe o desafio, submeta um _pull request_.
- Caso você tenha algum motivo para não submeter um _pull request_, crie um repositório privado no Github, faça todo desafio na branch **master** e não se esqueça de preencher o arquivo `pull-request.txt`. Tão logo termine seu desenvolvimento, adicione como colaborador o usuário `automator-hurb` no seu repositório e o deixe disponível por pelo menos 30 dias. **Não adicione o `automator-hurb` antes do término do desenvolvimento.**
- Caso você tenha algum problema para criar o repositório privado, ao término do desafio preencha o arquivo chamado `pull-request.txt`, comprima a pasta do projeto - incluindo a pasta `.git` - e nos envie por email.
- Para executar seu código, deve ser preciso apenas rodar os seguintes comandos:
- git clone \$seu-forkseu-fork
- comando para instalar dependências
- comando para executar a aplicação
* O projeto deve rodar utilizando apenas 1 comando (assumindo que a pessoa já tenha o minikube instalado e rodando).

## Critério de avaliação

- **Organização do código**: Separação de módulos, view e model, back-end e front-end
- **Organização do código**: Separação de módulos - código app e infra.
- **Clareza**: O README explica de forma resumida qual é o problema e como pode rodar a aplicação?
- **Assertividade**: A aplicação está fazendo o que é esperado? Se tem algo faltando, o README explica o porquê?
- **Legibilidade do código** (incluindo comentários)
- **Segurança**: Existe alguma vulnerabilidade clara?
- **Cobertura de testes** (Não esperamos cobertura completa)
- **Histórico de commits** (estrutura e qualidade)
- **Escolhas técnicas**: A escolha das bibliotecas, banco de dados, arquitetura, etc, é a melhor escolha para a aplicação?
- **Segurança**: Existe alguma vulnerabilidade clara que não tenha sido endereçada?
- **Cobertura de testes** Teste unitários
- **Histórico de commits** (estrutura e qualidade, titulos e descrição)
- **Escolhas técnicas**: A escolha das bibliotecas, arquitetura, etc, é a melhor escolha para a aplicação?
- **Comunicação**: Se você não conseguiu completar todo o teste, o README contém o que ficou faltando?

## Dúvidas

Expand Down
8 changes: 0 additions & 8 deletions database_schema.sql

This file was deleted.

16 changes: 0 additions & 16 deletions package.json

This file was deleted.

3 changes: 0 additions & 3 deletions pull-request.txt

This file was deleted.

Loading

0 comments on commit 635201a

Please sign in to comment.