Nefunguje inckludes: v common.neon + jak vyřešit odlišnou konfiguraci na vývojovém a produkčním serveru?

m.brecher
Generous Backer | 871
+
0
-

Ahoj,

potřebuji od zkušenějších kolegů poradit.

1 ) Jak vyřešit odlišnou konfiguraci vývojového a produkčního serveru

Konfiguraci nastavuji v souborech .neon takto:

/config/common.neon		    # obecná konfigurace
/config/services.neon		# služby
/config/local.neon		    # odlišné nastavení pro localhost - vývojový server (jiná databáze apod...)

Potřebuji, aby common.neon a services.neon byly aplikovány na vývojovém i produkčním serveru a local.neon přepsal některá nastavení která jsou na vývojovém serveru jinak.

Předpokládal jsem, že Nette automaticky zapne soubor local.neon jenom pro localhost, ale tak tomu není. Tak jsem na server nahrál verzi souboru local.neon se zakomentovanými nastaveními a na vývojovém serveru udržuji verzi bez komentářů. Je ale otravné toto neustále hlídat.

Rád bych to měl pořešené automaticky tak, aby Nette samo v produkčním prostředí (na produkčním serveru) soubor local.neon ignorovalo – nezávisle na tom, jestli je na produkční server nahrán.

Pátrám v dokumentaci, na fóru Nette, ale zatím jsem použitelné řešení nenašel.

1 )V konfiguraci .neon nefunguje inkludovat soubor local.neon

Konfigurační soubory jsem měl přidané v 1. verzi takto:

class Bootstrap
{
	public static function boot(): Configurator
	{
        $appDir = dirname(__DIR__);
		$configurator = new Configurator;

		........

		$configurator->addConfig($appDir . '/config/common.neon');
		$configurator->addConfig($appDir . '/config/services.neon');
		$configurator->addConfig($appDir . '/config/local.neon');

		return $configurator;
	}
}

Funguje to na vývojovém i produkčním serveru tak, že local.neon přepíše nastavení common.neon.

Zkoušel jsem i variantu s použitím includes: v souboru common.neon:

class Bootstrap
{
	public static function boot(): Configurator
	{
        $appDir = dirname(__DIR__);
		$configurator = new Configurator;

		........

		$configurator->addConfig($appDir . '/config/common.neon');
//		$configurator->addConfig($appDir . '/config/services.neon');
//		$configurator->addConfig($appDir . '/config/local.neon');

		return $configurator;
	}
}

common.neon:

includes:
	- services.neon
	- local.neon

Vložení souboru services.neon proběhlo v pořádku, ale soubor local.neon se nevložil – ani na vývojovém, ani na produkčním serveru. Žádnou chybu to nevyhodilo, jako kdybych ten řádek v common.neon zakomentoval.

Dotazy:

  • kde je chyba, že se nedaří local.neon inkludovat v konfiguraci, ale $configurator->addConfig($appDir . ‚/config/local.neon‘) funguje?
  • kdyby se local.neon podařilo nakonec nainkludovat, existuje v konfiguračním souboru .neon možnost podmíněného vykonání nějaké konfigurace – mám na mysli inkludovat soubor local.neon podle prostředí, něco jako v PHP:
if($isLocalServer){
	include 'local.neon'
}

Díky za jakékoliv rady.

Editoval m.brecher (14. 12. 2021 0:27)

m.brecher
Generous Backer | 871
+
0
-

Tak už jsem přišel na to, proč nefunguje vložení souboru local.neon do common.neon.

Soubor local.neon má změnit nastavení common.neon pro localhost, ale v dokumentaci nette je psáno:

Soubor, ve kterém je sekce includes uvedena, má vyšší prioritu než v něm vkládané soubory.

Soubor se sice vloží, ale má nižší prioritu, takže žádné nastavení změnit nemůže. Takže už jenom potřebuji poradit jak zajistit, aby se soubor local.neon nevložil na produkčním serveru – jestli by někdo měl osvědčené řešení?

Editoval m.brecher (14. 12. 2021 3:32)

David Grudl
Nette Core | 8227
+
+1
-

Prostě volej $configurator->addConfig($appDir . '/config/local.neon'); jen na lokálním stroji. Poznáš ho třeba podle toho, co vrací php_uname('n').

Šaman
Člen | 2663
+
+4
-

Co to řešíš? local.neon není od slova localhost(*), ale lokální nastavení – tedy úprava nastavení pro konkrétní stroj.
Při deployi se soubor local.neon ignoruje, stejně tak v gitu. Tento soubor se neverzuje. Jsou v něm citlivé údaje (typicky klíčky k databázi), které ani nechceš mít v žádném repozitáři.

Takže typické použití je, že na každém stroji je jiný local.neon. Všude se načítá, ale klidně může být i prázdný.


(*) No, vlastně je :)
I produkční server je z pohledu jeho konfigurace localhost.

Editoval Šaman (14. 12. 2021 11:21)

Kamil Valenta
Člen | 820
+
-2
-

Ano, to co popisuje @Šaman je také možné pojetí, ale já mám zkušenost, že se dřív nebo později vždy najde někdo, kdo local.neon naverzuje. Pokud ho deploy bude ignorovat, tak ještě OK.

My třeba máme na projektech neon pro produkční server, volitelně jeho části může přepsat neon pro vývojový server a volitelně jejich části může přepsat neon pro localhost. V tomto případě se více hodí pojetí, které nestínil @DavidGrudl, kdy se podmíněně natahují jen některé neony…

emololftw
Člen | 82
+
0
-

Já to třeba řeším ENV proměnnou. V dockeru mám:

php:
	environment:
		DOCKER_DEV: 'true'

pak v Bootstrap.php pouze kontroluji (bool)\getenv('DOCKER_DEV') a vím, že kdykoliv na localu pustím docker, vždy bude development mod 100%, toto řešení jsem musel aplikovat po několika nalhávání, že komentář v Bootstrap.php přece nezapomenu odstranit

Editoval emololftw (14. 12. 2021 10:59)

Šaman
Člen | 2663
+
+1
-

@KamilValenta: Mít v repozitáři konfiguraci produkčního serveru? Já jako programátor přece nemám mít přístup do produkční databáze. Mám kolik chci vývojových variant u sebe, pak je testovací server s dummy daty a úplně mimo mé kompetence běží produkční server s daty, na které vůbec nemám korporátní právo je vidět (např. v ekonomickém systému osobní data, podrobnosti pracovních smluv, výplaty), natož mít klíčky od produkční db.

A popravdě takové údaje ani nechci znát, protože kdyby se stal nějaký únik dat, teď jsem zcela mimo podezření.

Pavel Kravčík
Člen | 1195
+
+4
-

@KamilValenta, @Šaman: Z našeho pohledu máte pravdu oba. Verzujeme část produkčního neonu, klasicky CSP, různé hlavičky X- a pár dalších věcí typu routing cache. To se nahrává vždy přes CI. Údaje pro produkci však nepatří do Git. A local by určitě měl být ignore jak deploye tak gitu.

Kamil Valenta
Člen | 820
+
0
-

Šaman napsal(a):

@KamilValenta: Mít v repozitáři konfiguraci produkčního serveru? Já jako programátor přece nemám mít přístup do produkční databáze.

Ano, to jsou přeci dvě věci, které nemusí být nutně v jednom neonu. Ty jako programátor můžeš a máš mít přístup k hromadě direktiv, které naopak naverzovány být mají (název instace appky, identifikace subjektu klienta, ale třeba i GTM id apod.)

A právě díky tomu, že je to ve více samostatných souborech, s tím pak můžeš hezky pracovat a rozhodovat, co bude v bootstrapu nataženo / nenataženo, co bude / nebude na git naverzováno…

V mém případě se konfigurace produkčního serveru skládá i z desítek neonů (dle počtu povolených modulů a dle potřeb přepisů výchozích / nadřazených direktiv – protože i u neonů využívám něco jako „dědičnost“).

Šaman
Člen | 2663
+
+2
-

@KamilValenta: Mít víc neonů samozřejmě není problém. Mluvil jsem jen o tom jednom neverzovaném, který se liší server od serveru. A zjistil jsem, že správce serveru, ač není Netťák, si v local.neon přepisuje i některá nastavení z ostatních configů :)

V repozitáři pak máme verzovaný local.neon.example, který obsahuje šablonu naprostého minima pro doplnění informací (u malé aplikace typicky jen připojení k db a pro Laděnku email na správce).

Kamil Valenta
Člen | 820
+
0
-

@Šaman Rozumím. Já zase mluvím o tom, že u nás není rozhodující pro naverzování či nenaverzování, zda se něco jmenuje local.neon – i těch local.neon můžeme mít mnoho v jednom projektu, protože každý modul si může a nemusí nějaký svůj local.neon tahat. Prostě nejsem příznivec slívání čehokoliv do jednoho velkého souboru, ať už je to konfigurace nebo (v sousedním vláknu) konstanty.
Tvůj příklad s ekonomickým systémem je dobrý. Pokud pracujeme na e-shopu, je v local.neon daného modulu fiktivní API ERP. Tento neon je naverzovaný a zajistí, že žádný programátor z localhostu nepošle nic během testování do ERP klienta.

m.brecher
Generous Backer | 871
+
0
-

Ahoj,

díky za obsáhlé komentáře a rady.

Ráno s čistou hlavou mě hned napadlo jak to udělat a proč to jinak nejde.

  • soubor local.neon potřebuji aby přepsal nastavení databáze v common.neon
  • vložit ho jako includes: v common.neon nejde, protože common.neon má vyšší prioritu
  • jedinou možností je třída Bootstrap, kde se vložení local.neon do $configurator vhodně oifuje

Možností jak detekovat lokální (vývojový) server je více, normálně bych na to šel v presenteru standardní třídou Nette\Http\Request takto

$httpHost = $presenter->getHttpRequest()->getUrl()->getHost();  // $httpRequest není v Bootstrap.php ještě vytvořen
if($httpHost === 'localhost') { ... }

Tohle ale nejde v Bootstrap.php použít, není spuštěna application, nemáme ani $presenter, ani $httpRequest :(

Když nejde použít třída Nette, použijeme php proměnnou $_SERVER a problém je vyřešen:

class Bootstrap
{
	public static function boot(): Configurator
	{
        $appDir = dirname(__DIR__);
		$configurator = new Configurator;

		.......

		$configurator->addConfig($appDir . '/config/common.neon');
		$configurator->addConfig($appDir . '/config/services.neon');

        if($_SERVER['HTTP_HOST'] === 'localhost'){			// vyjímečně používám php, protože to jinak nejde
            $configurator->addConfig($appDir . '/config/local.neon');
        }

		return $configurator;
	}
}

Tohle funguje za všech okolností, nezávisle na tom, zda local.neon omylem nahraju na produkční server nebo ne. Nakonec to nebylo obtížné a mohl jsem si na to přijít hned sám ;)

Díky všem za obsáhlé příspěvky

Editoval m.brecher (14. 12. 2021 19:52)

m.brecher
Generous Backer | 871
+
0
-

Šaman napsal(a):

Co to řešíš? local.neon není od slova localhost(*), ale lokální nastavení – tedy úprava nastavení pro konkrétní stroj.
Při deployi se soubor local.neon ignoruje, stejně tak v gitu. Tento soubor se neverzuje. Jsou v něm citlivé údaje (typicky klíčky k databázi), které ani nechceš mít v žádném repozitáři.

Takže typické použití je, že na každém stroji je jiný local.neon. Všude se načítá, ale klidně může být i prázdný.


(*) No, vlastně je :)
I produkční server je z pohledu jeho konfigurace localhost.

Díky za doplnění znalostí, úprava nastavení pro konkrétní stroj tohle jsem nevěděl, já se na vývojový server vždycky díval jako na local/localhost stroj a produkční server jako „remote“ nebo „production“. Dlouhé roky jsem měl v php kódu „local“ použito právě pro prostředí na vývojovém serveru. Ale je správné to použít tak jak píšeš – je to nastavení na ten jeden konkrétní stroj na kterém to právě běží.

Nicméně pro moje (menší) projekty je ideální to řešit tak, že v common.neon je celé nastavení pro produkční server a soubor local.neon jenom „přepíše“ common.neon (databáze popř. něco dalšího). Když jsem se kouknul do startovacího projektu Nette na ty soubory tak jsem to takto intuitivně pochopil a přišlo mě to jako skvělá myšlenka to takhle řešit. A předpokládal jsem, že Nette samo bude detekovat prostředí a soubor local.neon vloží jenom na lokálním vývojovém serveru. Teď už chápu, že každý si deploy projektů dělá jinak a že je nevhodné, aby byl do Nette zabudován jeden konkrétní postup (který by vyhovoval jenom někomu) a je lepší, když si každý vyřeší odlišnosti vývojové/produkční prostředí jak mu vyhovuje.

m.brecher
Generous Backer | 871
+
0
-

Šaman napsal(a):

@KamilValenta: Mít v repozitáři konfiguraci produkčního serveru? Já jako programátor přece nemám mít přístup do produkční databáze. Mám kolik chci vývojových variant u sebe, pak je testovací server s dummy daty a úplně mimo mé kompetence běží produkční server s daty, na které vůbec nemám korporátní právo je vidět (např. v ekonomickém systému osobní data, podrobnosti pracovních smluv, výplaty), natož mít klíčky od produkční db.

A popravdě takové údaje ani nechci znát, protože kdyby se stal nějaký únik dat, teď jsem zcela mimo podezření.

Ano, u větších projektů je to tak nejlepší – vůbec nemít přístup k ostrým datům. Ale já dělám menší CMS-ka, různé menší aplikace, malé eshopky, kde klient nikdy nemá vlastní IT specialisty, takže tam táhnu vývoj, deploy i správu ostrých dat od začátku do konce.

A skvělé na Nette je právě to, že umožňuje nejen profesionální podporu velkých a složitých projektů, ale je současně dostatečně malé a kompaktní na to, aby se vyplatilo i na úplně malých projektech. Proto jsem si Nette vybral.